diff -druN linux-libre-3.6-gnu/arch/alpha/kernel/process.c linux-libre-3.6.3-gnu/arch/alpha/kernel/process.c
--- linux-libre-3.6-gnu/arch/alpha/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/alpha/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/reg.h>
 #include <asm/uaccess.h>
@@ -54,8 +55,10 @@
 		/* FIXME -- EV6 and LCA45 know how to power down
 		   the CPU.  */
 
+		rcu_idle_enter();
 		while (!need_resched())
 			cpu_relax();
+		rcu_idle_exit();
 		schedule();
 	}
 }
diff -druN linux-libre-3.6-gnu/arch/arm/include/asm/syscall.h linux-libre-3.6.3-gnu/arch/arm/include/asm/syscall.h
--- linux-libre-3.6-gnu/arch/arm/include/asm/syscall.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/arm/include/asm/syscall.h	2012-10-21 12:32:56.000000000 -0400
@@ -8,6 +8,7 @@
 #define _ASM_ARM_SYSCALL_H
 
 #include <linux/err.h>
+#include <linux/sched.h>
 
 extern const unsigned long sys_call_table[];
 
diff -druN linux-libre-3.6-gnu/arch/arm/include/asm/vfpmacros.h linux-libre-3.6.3-gnu/arch/arm/include/asm/vfpmacros.h
--- linux-libre-3.6-gnu/arch/arm/include/asm/vfpmacros.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/arm/include/asm/vfpmacros.h	2012-10-21 12:32:56.000000000 -0400
@@ -28,7 +28,7 @@
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
 	tst	\tmp, #HWCAP_VFPv3D16
-	ldceq	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
+	ldceql	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
 	addne	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
@@ -52,7 +52,7 @@
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
 	tst	\tmp, #HWCAP_VFPv3D16
-	stceq	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
+	stceql	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
 	addne	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
diff -druN linux-libre-3.6-gnu/arch/arm/Kconfig linux-libre-3.6.3-gnu/arch/arm/Kconfig
--- linux-libre-3.6-gnu/arch/arm/Kconfig	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/arm/Kconfig	2012-10-21 12:32:56.000000000 -0400
@@ -1413,6 +1413,16 @@
 	  on systems with an outer cache, the store buffer is drained
 	  explicitly.
 
+config ARM_ERRATA_775420
+       bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
+       depends on CPU_V7
+       help
+	 This option enables the workaround for the 775420 Cortex-A9 (r2p2,
+	 r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance
+	 operation aborts with MMU exception, it might cause the processor
+	 to deadlock. This workaround puts DSB before executing ISB if
+	 an abort may occur on cache maintenance.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
diff -druN linux-libre-3.6-gnu/arch/arm/mm/cache-v7.S linux-libre-3.6.3-gnu/arch/arm/mm/cache-v7.S
--- linux-libre-3.6-gnu/arch/arm/mm/cache-v7.S	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/arm/mm/cache-v7.S	2012-10-21 12:32:56.000000000 -0400
@@ -211,6 +211,9 @@
  * isn't mapped, fail with -EFAULT.
  */
 9001:
+#ifdef CONFIG_ARM_ERRATA_775420
+	dsb
+#endif
 	mov	r0, #-EFAULT
 	mov	pc, lr
  UNWIND(.fnend		)
diff -druN linux-libre-3.6-gnu/arch/arm/plat-omap/counter_32k.c linux-libre-3.6.3-gnu/arch/arm/plat-omap/counter_32k.c
--- linux-libre-3.6-gnu/arch/arm/plat-omap/counter_32k.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/arm/plat-omap/counter_32k.c	2012-10-21 12:32:56.000000000 -0400
@@ -55,22 +55,29 @@
  * nsecs and adds to a monotonically increasing timespec.
  */
 static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
+static cycles_t cycles;
 static unsigned int persistent_mult, persistent_shift;
+static DEFINE_SPINLOCK(read_persistent_clock_lock);
+
 static void omap_read_persistent_clock(struct timespec *ts)
 {
 	unsigned long long nsecs;
-	cycles_t delta;
-	struct timespec *tsp = &persistent_ts;
+	cycles_t last_cycles;
+	unsigned long flags;
+
+	spin_lock_irqsave(&read_persistent_clock_lock, flags);
 
 	last_cycles = cycles;
 	cycles = sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0;
-	delta = cycles - last_cycles;
 
-	nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift);
+	nsecs = clocksource_cyc2ns(cycles - last_cycles,
+					persistent_mult, persistent_shift);
 
-	timespec_add_ns(tsp, nsecs);
-	*ts = *tsp;
+	timespec_add_ns(&persistent_ts, nsecs);
+
+	*ts = persistent_ts;
+
+	spin_unlock_irqrestore(&read_persistent_clock_lock, flags);
 }
 
 /**
diff -druN linux-libre-3.6-gnu/arch/arm/plat-omap/include/plat/omap-serial.h linux-libre-3.6.3-gnu/arch/arm/plat-omap/include/plat/omap-serial.h
--- linux-libre-3.6-gnu/arch/arm/plat-omap/include/plat/omap-serial.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/arm/plat-omap/include/plat/omap-serial.h	2012-10-21 12:32:56.000000000 -0400
@@ -42,10 +42,10 @@
 #define OMAP_UART_WER_MOD_WKUP	0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX		0x04
+#define OMAP_UART_SW_TX		0x8
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX		0x04
+#define OMAP_UART_SW_RX		0x2
 
 #define OMAP_UART_SYSC_RESET	0X07
 #define OMAP_UART_TCR_TRIG	0X0F
diff -druN linux-libre-3.6-gnu/arch/cris/kernel/process.c linux-libre-3.6.3-gnu/arch/cris/kernel/process.c
--- linux-libre-3.6-gnu/arch/cris/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/cris/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/elfcore.h>
 #include <linux/mqueue.h>
 #include <linux/reboot.h>
+#include <linux/rcupdate.h>
 
 //#define DEBUG
 
@@ -74,6 +75,7 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			void (*idle)(void);
 			/*
@@ -86,6 +88,7 @@
 				idle = default_idle;
 			idle();
 		}
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff -druN linux-libre-3.6-gnu/arch/frv/kernel/process.c linux-libre-3.6.3-gnu/arch/frv/kernel/process.c
--- linux-libre-3.6-gnu/arch/frv/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/frv/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
+#include <linux/rcupdate.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/uaccess.h>
@@ -69,12 +70,14 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			check_pgt_cache();
 
 			if (!frv_dma_inprogress && idle)
 				idle();
 		}
+		rcu_idle_exit();
 
 		schedule_preempt_disabled();
 	}
diff -druN linux-libre-3.6-gnu/arch/h8300/kernel/process.c linux-libre-3.6.3-gnu/arch/h8300/kernel/process.c
--- linux-libre-3.6-gnu/arch/h8300/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/h8300/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/reboot.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/traps.h>
@@ -78,8 +79,10 @@
 void cpu_idle(void)
 {
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			idle();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff -druN linux-libre-3.6-gnu/arch/ia64/kernel/process.c linux-libre-3.6.3-gnu/arch/ia64/kernel/process.c
--- linux-libre-3.6-gnu/arch/ia64/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/ia64/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/kdebug.h>
 #include <linux/utsname.h>
 #include <linux/tracehook.h>
+#include <linux/rcupdate.h>
 
 #include <asm/cpu.h>
 #include <asm/delay.h>
@@ -279,6 +280,7 @@
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		if (can_do_pal_halt) {
 			current_thread_info()->status &= ~TS_POLLING;
 			/*
@@ -309,6 +311,7 @@
 			normal_xtp();
 #endif
 		}
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 		check_pgt_cache();
 		if (cpu_is_offline(cpu))
diff -druN linux-libre-3.6-gnu/arch/m32r/kernel/process.c linux-libre-3.6.3-gnu/arch/m32r/kernel/process.c
--- linux-libre-3.6-gnu/arch/m32r/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/m32r/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/hardirq.h>
+#include <linux/rcupdate.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -82,6 +83,7 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			void (*idle)(void) = pm_idle;
 
@@ -90,6 +92,7 @@
 
 			idle();
 		}
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff -druN linux-libre-3.6-gnu/arch/m68k/kernel/process.c linux-libre-3.6.3-gnu/arch/m68k/kernel/process.c
--- linux-libre-3.6-gnu/arch/m68k/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/m68k/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/reboot.h>
 #include <linux/init_task.h>
 #include <linux/mqueue.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/traps.h>
@@ -75,8 +76,10 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			idle();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff -druN linux-libre-3.6-gnu/arch/mips/ath79/clock.c linux-libre-3.6.3-gnu/arch/mips/ath79/clock.c
--- linux-libre-3.6-gnu/arch/mips/ath79/clock.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mips/ath79/clock.c	2012-10-21 12:32:56.000000000 -0400
@@ -17,6 +17,8 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 
+#include <asm/div64.h>
+
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
@@ -166,11 +168,34 @@
 	ath79_uart_clk.rate = ath79_ref_clk.rate;
 }
 
+static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
+				      u32 frac, u32 out_div)
+{
+	u64 t;
+	u32 ret;
+
+	t = ath79_ref_clk.rate;
+	t *= nint;
+	do_div(t, ref_div);
+	ret = t;
+
+	t = ath79_ref_clk.rate;
+	t *= nfrac;
+	do_div(t, ref_div * frac);
+	ret += t;
+
+	ret /= (1 << out_div);
+	return ret;
+}
+
 static void __init ar934x_clocks_init(void)
 {
-	u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
+	u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
 	u32 cpu_pll, ddr_pll;
 	u32 bootstrap;
+	void __iomem *dpll_base;
+
+	dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE);
 
 	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
 	if (bootstrap &	AR934X_BOOTSTRAP_REF_CLK_40)
@@ -178,33 +203,59 @@
 	else
 		ath79_ref_clk.rate = 25 * 1000 * 1000;
 
-	pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
-	out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
-		  AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
-	ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
-		  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
-	nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
-	       AR934X_PLL_CPU_CONFIG_NINT_MASK;
-	frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
-	       AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
+	pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG);
+	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
+		pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG);
+		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
+		       AR934X_SRIF_DPLL1_NINT_MASK;
+		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
+		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
+			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+		frac = 1 << 18;
+	} else {
+		pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
+		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
+		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
+		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
+		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
+		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
+			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
+		frac = 1 << 6;
+	}
 
-	cpu_pll = nint * ath79_ref_clk.rate / ref_div;
-	cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 6));
-	cpu_pll /= (1 << out_div);
+	cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
 
-	pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
-	out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
-		  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
-	ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
-		  AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
-	nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
-	       AR934X_PLL_DDR_CONFIG_NINT_MASK;
-	frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
-	       AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
+	pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG);
+	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
+		pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG);
+		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
+		       AR934X_SRIF_DPLL1_NINT_MASK;
+		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
+		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
+			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+		frac = 1 << 18;
+	} else {
+		pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
+		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+			  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
+		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+			   AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
+		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
+		       AR934X_PLL_DDR_CONFIG_NINT_MASK;
+		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
+			AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
+		frac = 1 << 10;
+	}
 
-	ddr_pll = nint * ath79_ref_clk.rate / ref_div;
-	ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 10));
-	ddr_pll /= (1 << out_div);
+	ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
 
 	clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
 
@@ -240,6 +291,8 @@
 
 	ath79_wdt_clk.rate = ath79_ref_clk.rate;
 	ath79_uart_clk.rate = ath79_ref_clk.rate;
+
+	iounmap(dpll_base);
 }
 
 void __init ath79_clocks_init(void)
diff -druN linux-libre-3.6-gnu/arch/mips/include/asm/mach-ath79/ar71xx_regs.h linux-libre-3.6.3-gnu/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
--- linux-libre-3.6-gnu/arch/mips/include/asm/mach-ath79/ar71xx_regs.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mips/include/asm/mach-ath79/ar71xx_regs.h	2012-10-21 12:32:56.000000000 -0400
@@ -63,6 +63,8 @@
 
 #define AR934X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
 #define AR934X_WMAC_SIZE	0x20000
+#define AR934X_SRIF_BASE	(AR71XX_APB_BASE + 0x00116000)
+#define AR934X_SRIF_SIZE	0x1000
 
 /*
  * DDR_CTRL block
@@ -399,4 +401,25 @@
 #define AR933X_GPIO_COUNT		30
 #define AR934X_GPIO_COUNT		23
 
+/*
+ * SRIF block
+ */
+#define AR934X_SRIF_CPU_DPLL1_REG	0x1c0
+#define AR934X_SRIF_CPU_DPLL2_REG	0x1c4
+#define AR934X_SRIF_CPU_DPLL3_REG	0x1c8
+
+#define AR934X_SRIF_DDR_DPLL1_REG	0x240
+#define AR934X_SRIF_DDR_DPLL2_REG	0x244
+#define AR934X_SRIF_DDR_DPLL3_REG	0x248
+
+#define AR934X_SRIF_DPLL1_REFDIV_SHIFT	27
+#define AR934X_SRIF_DPLL1_REFDIV_MASK	0x1f
+#define AR934X_SRIF_DPLL1_NINT_SHIFT	18
+#define AR934X_SRIF_DPLL1_NINT_MASK	0x1ff
+#define AR934X_SRIF_DPLL1_NFRAC_MASK	0x0003ffff
+
+#define AR934X_SRIF_DPLL2_LOCAL_PLL	BIT(30)
+#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT	13
+#define AR934X_SRIF_DPLL2_OUTDIV_MASK	0x7
+
 #endif /* __ASM_MACH_AR71XX_REGS_H */
diff -druN linux-libre-3.6-gnu/arch/mips/kernel/kgdb.c linux-libre-3.6.3-gnu/arch/mips/kernel/kgdb.c
--- linux-libre-3.6-gnu/arch/mips/kernel/kgdb.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mips/kernel/kgdb.c	2012-10-21 12:32:56.000000000 -0400
@@ -283,6 +283,15 @@
 	struct pt_regs *regs = args->regs;
 	int trap = (regs->cp0_cause & 0x7c) >> 2;
 
+#ifdef CONFIG_KPROBES
+	/*
+	 * Return immediately if the kprobes fault notifier has set
+	 * DIE_PAGE_FAULT.
+	 */
+	if (cmd == DIE_PAGE_FAULT)
+		return NOTIFY_DONE;
+#endif /* CONFIG_KPROBES */
+
 	/* Userspace events, ignore. */
 	if (user_mode(regs))
 		return NOTIFY_DONE;
diff -druN linux-libre-3.6-gnu/arch/mips/kernel/Makefile linux-libre-3.6.3-gnu/arch/mips/kernel/Makefile
--- linux-libre-3.6-gnu/arch/mips/kernel/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mips/kernel/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -104,7 +104,7 @@
 
 obj-$(CONFIG_OF)		+= prom.o
 
-CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+= 8250-platform.o
 
diff -druN linux-libre-3.6-gnu/arch/mips/Makefile linux-libre-3.6.3-gnu/arch/mips/Makefile
--- linux-libre-3.6-gnu/arch/mips/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mips/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -225,7 +225,7 @@
 LDFLAGS			+= -m $(ld-emul)
 
 ifdef CONFIG_MIPS
-CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \
+CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
 	egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
 	sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/")
 ifdef CONFIG_64BIT
diff -druN linux-libre-3.6-gnu/arch/mn10300/kernel/process.c linux-libre-3.6.3-gnu/arch/mn10300/kernel/process.c
--- linux-libre-3.6-gnu/arch/mn10300/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mn10300/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -107,6 +108,7 @@
 {
 	/* endless idle loop with no priority at all */
 	for (;;) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			void (*idle)(void);
 
@@ -121,6 +123,7 @@
 			}
 			idle();
 		}
+		rcu_idle_exit();
 
 		schedule_preempt_disabled();
 	}
diff -druN linux-libre-3.6-gnu/arch/mn10300/Makefile linux-libre-3.6.3-gnu/arch/mn10300/Makefile
--- linux-libre-3.6-gnu/arch/mn10300/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/mn10300/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -26,7 +26,7 @@
 PROCESSOR	:= unset
 UNIT		:= unset
 
-KBUILD_CFLAGS	+= -mam33 -mmem-funcs -DCPU=AM33
+KBUILD_CFLAGS	+= -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,)
 KBUILD_AFLAGS	+= -mam33 -DCPU=AM33
 
 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y)
diff -druN linux-libre-3.6-gnu/arch/parisc/kernel/process.c linux-libre-3.6.3-gnu/arch/parisc/kernel/process.c
--- linux-libre-3.6-gnu/arch/parisc/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/parisc/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -48,6 +48,7 @@
 #include <linux/unistd.h>
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
+#include <linux/rcupdate.h>
 
 #include <asm/io.h>
 #include <asm/asm-offsets.h>
@@ -69,8 +70,10 @@
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			barrier();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 		check_pgt_cache();
 	}
diff -druN linux-libre-3.6-gnu/arch/powerpc/include/asm/pci-bridge.h linux-libre-3.6.3-gnu/arch/powerpc/include/asm/pci-bridge.h
--- linux-libre-3.6-gnu/arch/powerpc/include/asm/pci-bridge.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/powerpc/include/asm/pci-bridge.h	2012-10-21 12:32:56.000000000 -0400
@@ -182,6 +182,14 @@
 #if defined(CONFIG_EEH)
 static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 {
+	/*
+	 * For those OF nodes whose parent isn't PCI bridge, they
+	 * don't have PCI_DN actually. So we have to skip them for
+	 * any EEH operations.
+	 */
+	if (!dn || !PCI_DN(dn))
+		return NULL;
+
 	return PCI_DN(dn)->edev;
 }
 #endif
diff -druN linux-libre-3.6-gnu/arch/powerpc/kernel/iommu.c linux-libre-3.6.3-gnu/arch/powerpc/kernel/iommu.c
--- linux-libre-3.6-gnu/arch/powerpc/kernel/iommu.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/powerpc/kernel/iommu.c	2012-10-21 12:32:56.000000000 -0400
@@ -215,7 +215,8 @@
 	spin_lock_irqsave(&(pool->lock), flags);
 
 again:
-	if ((pass == 0) && handle && *handle)
+	if ((pass == 0) && handle && *handle &&
+	    (*handle >= pool->start) && (*handle < pool->end))
 		start = *handle;
 	else
 		start = pool->hint;
@@ -236,7 +237,9 @@
 		 * but on second pass, start at 0 in pool 0.
 		 */
 		if ((start & mask) >= limit || pass > 0) {
+			spin_unlock(&(pool->lock));
 			pool = &(tbl->pools[0]);
+			spin_lock(&(pool->lock));
 			start = pool->start;
 		} else {
 			start &= mask;
diff -druN linux-libre-3.6-gnu/arch/powerpc/lib/memcpy_power7.S linux-libre-3.6.3-gnu/arch/powerpc/lib/memcpy_power7.S
--- linux-libre-3.6-gnu/arch/powerpc/lib/memcpy_power7.S	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/powerpc/lib/memcpy_power7.S	2012-10-21 12:32:56.000000000 -0400
@@ -239,8 +239,8 @@
 	ori	r9,r9,1		/* stream=1 */
 
 	srdi	r7,r5,7		/* length in cachelines, capped at 0x3FF */
-	cmpldi	cr1,r7,0x3FF
-	ble	cr1,1f
+	cmpldi	r7,0x3FF
+	ble	1f
 	li	r7,0x3FF
 1:	lis	r0,0x0E00	/* depth=7 */
 	sldi	r7,r7,7
diff -druN linux-libre-3.6-gnu/arch/powerpc/platforms/pseries/eeh.c linux-libre-3.6.3-gnu/arch/powerpc/platforms/pseries/eeh.c
--- linux-libre-3.6-gnu/arch/powerpc/platforms/pseries/eeh.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/powerpc/platforms/pseries/eeh.c	2012-10-21 12:32:56.000000000 -0400
@@ -1029,7 +1029,7 @@
 {
 	struct pci_controller *phb;
 
-	if (!dn || !of_node_to_eeh_dev(dn))
+	if (!of_node_to_eeh_dev(dn))
 		return;
 	phb = of_node_to_eeh_dev(dn)->phb;
 
diff -druN linux-libre-3.6-gnu/arch/powerpc/sysdev/dart_iommu.c linux-libre-3.6.3-gnu/arch/powerpc/sysdev/dart_iommu.c
--- linux-libre-3.6-gnu/arch/powerpc/sysdev/dart_iommu.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/powerpc/sysdev/dart_iommu.c	2012-10-21 12:32:56.000000000 -0400
@@ -74,11 +74,16 @@
 
 #define DBG(...)
 
+static DEFINE_SPINLOCK(invalidate_lock);
+
 static inline void dart_tlb_invalidate_all(void)
 {
 	unsigned long l = 0;
 	unsigned int reg, inv_bit;
 	unsigned long limit;
+	unsigned long flags;
+
+	spin_lock_irqsave(&invalidate_lock, flags);
 
 	DBG("dart: flush\n");
 
@@ -111,12 +116,17 @@
 			panic("DART: TLB did not flush after waiting a long "
 			      "time. Buggy U3 ?");
 	}
+
+	spin_unlock_irqrestore(&invalidate_lock, flags);
 }
 
 static inline void dart_tlb_invalidate_one(unsigned long bus_rpn)
 {
 	unsigned int reg;
 	unsigned int l, limit;
+	unsigned long flags;
+
+	spin_lock_irqsave(&invalidate_lock, flags);
 
 	reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE |
 		(bus_rpn & DART_CNTL_U4_IONE_MASK);
@@ -138,6 +148,8 @@
 			panic("DART: TLB did not flush after waiting a long "
 			      "time. Buggy U4 ?");
 	}
+
+	spin_unlock_irqrestore(&invalidate_lock, flags);
 }
 
 static void dart_flush(struct iommu_table *tbl)
diff -druN linux-libre-3.6-gnu/arch/score/kernel/process.c linux-libre-3.6.3-gnu/arch/score/kernel/process.c
--- linux-libre-3.6-gnu/arch/score/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/score/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/reboot.h>
 #include <linux/elfcore.h>
 #include <linux/pm.h>
+#include <linux/rcupdate.h>
 
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -50,9 +51,10 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			barrier();
-
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff -druN linux-libre-3.6-gnu/arch/x86/boot/compressed/Makefile linux-libre-3.6.3-gnu/arch/x86/boot/compressed/Makefile
--- linux-libre-3.6-gnu/arch/x86/boot/compressed/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/x86/boot/compressed/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -28,6 +28,9 @@
 	$(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
 	$(obj)/piggy.o
 
+$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
+$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone
+
 ifeq ($(CONFIG_EFI_STUB), y)
 	VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
 endif
diff -druN linux-libre-3.6-gnu/arch/x86/include/asm/pgtable.h linux-libre-3.6.3-gnu/arch/x86/include/asm/pgtable.h
--- linux-libre-3.6-gnu/arch/x86/include/asm/pgtable.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/x86/include/asm/pgtable.h	2012-10-21 12:32:56.000000000 -0400
@@ -146,8 +146,7 @@
 
 static inline int pmd_large(pmd_t pte)
 {
-	return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
-		(_PAGE_PSE | _PAGE_PRESENT);
+	return pmd_flags(pte) & _PAGE_PSE;
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -415,7 +414,13 @@
 
 static inline int pmd_present(pmd_t pmd)
 {
-	return pmd_flags(pmd) & _PAGE_PRESENT;
+	/*
+	 * Checking for _PAGE_PSE is needed too because
+	 * split_huge_page will temporarily clear the present bit (but
+	 * the _PAGE_PSE flag will remain set at all times while the
+	 * _PAGE_PRESENT bit is clear).
+	 */
+	return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE);
 }
 
 static inline int pmd_none(pmd_t pmd)
diff -druN linux-libre-3.6-gnu/arch/x86/Makefile linux-libre-3.6.3-gnu/arch/x86/Makefile
--- linux-libre-3.6-gnu/arch/x86/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/x86/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -92,7 +92,7 @@
 ifdef CONFIG_X86_X32
 	x32_ld_ok := $(call try-run,\
 			/bin/echo -e '1: .quad 1b' | \
-			$(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" - && \
+			$(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \
 			$(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMPO" && \
 			$(LD) -m elf32_x86_64 "$$TMPO" -o "$$TMP",y,n)
         ifeq ($(x32_ld_ok),y)
diff -druN linux-libre-3.6-gnu/arch/x86/platform/efi/efi.c linux-libre-3.6.3-gnu/arch/x86/platform/efi/efi.c
--- linux-libre-3.6-gnu/arch/x86/platform/efi/efi.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/x86/platform/efi/efi.c	2012-10-21 12:32:56.000000000 -0400
@@ -890,6 +890,7 @@
 	 *
 	 * Call EFI services through wrapper functions.
 	 */
+	efi.runtime_version = efi_systab.fw_revision;
 	efi.get_time = virt_efi_get_time;
 	efi.set_time = virt_efi_set_time;
 	efi.get_wakeup_time = virt_efi_get_wakeup_time;
diff -druN linux-libre-3.6-gnu/arch/x86/xen/enlighten.c linux-libre-3.6.3-gnu/arch/x86/xen/enlighten.c
--- linux-libre-3.6-gnu/arch/x86/xen/enlighten.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/x86/xen/enlighten.c	2012-10-21 12:32:56.000000000 -0400
@@ -984,7 +984,16 @@
 
 	native_write_cr4(cr4);
 }
-
+#ifdef CONFIG_X86_64
+static inline unsigned long xen_read_cr8(void)
+{
+	return 0;
+}
+static inline void xen_write_cr8(unsigned long val)
+{
+	BUG_ON(val);
+}
+#endif
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
 	int ret;
@@ -1153,6 +1162,11 @@
 	.read_cr4_safe = native_read_cr4_safe,
 	.write_cr4 = xen_write_cr4,
 
+#ifdef CONFIG_X86_64
+	.read_cr8 = xen_read_cr8,
+	.write_cr8 = xen_write_cr8,
+#endif
+
 	.wbinvd = native_wbinvd,
 
 	.read_msr = native_read_msr_safe,
@@ -1161,6 +1175,8 @@
 	.read_tsc = native_read_tsc,
 	.read_pmc = native_read_pmc,
 
+	.read_tscp = native_read_tscp,
+
 	.iret = xen_iret,
 	.irq_enable_sysexit = xen_sysexit,
 #ifdef CONFIG_X86_64
diff -druN linux-libre-3.6-gnu/arch/xtensa/kernel/process.c linux-libre-3.6.3-gnu/arch/xtensa/kernel/process.c
--- linux-libre-3.6-gnu/arch/xtensa/kernel/process.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/arch/xtensa/kernel/process.c	2012-10-21 12:32:56.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/mqueue.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -110,8 +111,10 @@
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			platform_idle();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff -druN linux-libre-3.6-gnu/block/blk-core.c linux-libre-3.6.3-gnu/block/blk-core.c
--- linux-libre-3.6-gnu/block/blk-core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/block/blk-core.c	2012-10-21 12:32:56.000000000 -0400
@@ -696,7 +696,7 @@
 	q->request_fn		= rfn;
 	q->prep_rq_fn		= NULL;
 	q->unprep_rq_fn		= NULL;
-	q->queue_flags		= QUEUE_FLAG_DEFAULT;
+	q->queue_flags		|= QUEUE_FLAG_DEFAULT;
 
 	/* Override internal queue lock with supplied lock pointer */
 	if (lock)
diff -druN linux-libre-3.6-gnu/drivers/acpi/bus.c linux-libre-3.6.3-gnu/drivers/acpi/bus.c
--- linux-libre-3.6-gnu/drivers/acpi/bus.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/acpi/bus.c	2012-10-21 12:32:56.000000000 -0400
@@ -994,8 +994,6 @@
 	status = acpi_ec_ecdt_probe();
 	/* Ignore result. Not having an ECDT is not fatal. */
 
-	acpi_bus_osc_support();
-
 	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
@@ -1003,6 +1001,12 @@
 	}
 
 	/*
+	 * _OSC method may exist in module level code,
+	 * so it must be run after ACPI_FULL_INITIALIZATION
+	 */
+	acpi_bus_osc_support();
+
+	/*
 	 * _PDC control method may load dynamic SSDT tables,
 	 * and we need to install the table handler before that.
 	 */
diff -druN linux-libre-3.6-gnu/drivers/acpi/ec.c linux-libre-3.6.3-gnu/drivers/acpi/ec.c
--- linux-libre-3.6-gnu/drivers/acpi/ec.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/acpi/ec.c	2012-10-21 12:32:56.000000000 -0400
@@ -71,9 +71,6 @@
 #define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
 #define ACPI_EC_MSI_UDELAY	550	/* Wait 550us for MSI EC */
 
-#define ACPI_EC_STORM_THRESHOLD 8	/* number of false interrupts
-					   per one transaction */
-
 enum {
 	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
 	EC_FLAGS_GPE_STORM,		/* GPE storm detected */
@@ -87,6 +84,15 @@
 module_param(ec_delay, uint, 0644);
 MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
 
+/*
+ * If the number of false interrupts per one transaction exceeds
+ * this threshold, will think there is a GPE storm happened and
+ * will disable the GPE for normal transaction.
+ */
+static unsigned int ec_storm_threshold  __read_mostly = 8;
+module_param(ec_storm_threshold, uint, 0644);
+MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
+
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
 /* External interfaces use first EC only, so remember */
 typedef int (*acpi_ec_query_func) (void *data);
@@ -319,7 +325,7 @@
 		msleep(1);
 		/* It is safe to enable the GPE outside of the transaction. */
 		acpi_enable_gpe(NULL, ec->gpe);
-	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
+	} else if (t->irq_count > ec_storm_threshold) {
 		pr_info(PREFIX "GPE storm detected, "
 			"transactions will use polling mode\n");
 		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
@@ -924,6 +930,17 @@
 	return 0;
 }
 
+/*
+ * Clevo M720 notebook actually works ok with IRQ mode, if we lifted
+ * the GPE storm threshold back to 20
+ */
+static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
+{
+	pr_debug("Setting the EC GPE storm threshold to 20\n");
+	ec_storm_threshold  = 20;
+	return 0;
+}
+
 static struct dmi_system_id __initdata ec_dmi_table[] = {
 	{
 	ec_skip_dsdt_scan, "Compal JFL92", {
@@ -955,10 +972,13 @@
 	{
 	ec_validate_ecdt, "ASUS hardware", {
 	DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
+	{
+	ec_enlarge_storm_threshold, "CLEVO hardware", {
+	DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+	DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL},
 	{},
 };
 
-
 int __init acpi_ec_ecdt_probe(void)
 {
 	acpi_status status;
diff -druN linux-libre-3.6-gnu/drivers/base/power/main.c linux-libre-3.6.3-gnu/drivers/base/power/main.c
--- linux-libre-3.6-gnu/drivers/base/power/main.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/base/power/main.c	2012-10-21 12:32:56.000000000 -0400
@@ -996,7 +996,7 @@
 
 	error = dpm_suspend_noirq(state);
 	if (error) {
-		dpm_resume_early(state);
+		dpm_resume_early(resume_event(state));
 		return error;
 	}
 
diff -druN linux-libre-3.6-gnu/drivers/char/tpm/tpm.c linux-libre-3.6.3-gnu/drivers/char/tpm/tpm.c
--- linux-libre-3.6-gnu/drivers/char/tpm/tpm.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/char/tpm/tpm.c	2012-10-21 12:32:56.000000000 -0400
@@ -1186,17 +1186,20 @@
 		  size_t size, loff_t *off)
 {
 	struct tpm_chip *chip = file->private_data;
-	size_t in_size = size, out_size;
+	size_t in_size = size;
+	ssize_t out_size;
 
 	/* cannot perform a write until the read has cleared
-	   either via tpm_read or a user_read_timer timeout */
-	while (atomic_read(&chip->data_pending) != 0)
-		msleep(TPM_TIMEOUT);
-
-	mutex_lock(&chip->buffer_mutex);
+	   either via tpm_read or a user_read_timer timeout.
+	   This also prevents splitted buffered writes from blocking here.
+	*/
+	if (atomic_read(&chip->data_pending) != 0)
+		return -EBUSY;
 
 	if (in_size > TPM_BUFSIZE)
-		in_size = TPM_BUFSIZE;
+		return -E2BIG;
+
+	mutex_lock(&chip->buffer_mutex);
 
 	if (copy_from_user
 	    (chip->data_buffer, (void __user *) buf, in_size)) {
@@ -1206,6 +1209,10 @@
 
 	/* atomic tpm command send and result receive */
 	out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+	if (out_size < 0) {
+		mutex_unlock(&chip->buffer_mutex);
+		return out_size;
+	}
 
 	atomic_set(&chip->data_pending, out_size);
 	mutex_unlock(&chip->buffer_mutex);
diff -druN linux-libre-3.6-gnu/drivers/char/ttyprintk.c linux-libre-3.6.3-gnu/drivers/char/ttyprintk.c
--- linux-libre-3.6-gnu/drivers/char/ttyprintk.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/char/ttyprintk.c	2012-10-21 12:32:56.000000000 -0400
@@ -67,7 +67,7 @@
 				tmp[tpk_curr + 1] = '\0';
 				printk(KERN_INFO "%s%s", tpk_tag, tmp);
 				tpk_curr = 0;
-				if (buf[i + 1] == '\n')
+				if ((i + 1) < count && buf[i + 1] == '\n')
 					i++;
 				break;
 			case '\n':
diff -druN linux-libre-3.6-gnu/drivers/dma/dmaengine.c linux-libre-3.6.3-gnu/drivers/dma/dmaengine.c
--- linux-libre-3.6-gnu/drivers/dma/dmaengine.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/dma/dmaengine.c	2012-10-21 12:32:56.000000000 -0400
@@ -582,7 +582,7 @@
 				list_del_rcu(&device->global_node);
 				break;
 			} else if (err)
-				pr_err("%s: failed to get %s: (%d)\n",
+				pr_debug("%s: failed to get %s: (%d)\n",
 				       __func__, dma_chan_name(chan), err);
 		}
 	}
diff -druN linux-libre-3.6-gnu/drivers/firewire/core-cdev.c linux-libre-3.6.3-gnu/drivers/firewire/core-cdev.c
--- linux-libre-3.6-gnu/drivers/firewire/core-cdev.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/firewire/core-cdev.c	2012-10-21 12:32:56.000000000 -0400
@@ -473,8 +473,8 @@
 	client->bus_reset_closure = a->bus_reset_closure;
 	if (a->bus_reset != 0) {
 		fill_bus_reset_event(&bus_reset, client);
-		ret = copy_to_user(u64_to_uptr(a->bus_reset),
-				   &bus_reset, sizeof(bus_reset));
+		/* unaligned size of bus_reset is 36 bytes */
+		ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36);
 	}
 	if (ret == 0 && list_empty(&client->link))
 		list_add_tail(&client->link, &client->device->client_list);
diff -druN linux-libre-3.6-gnu/drivers/firmware/efivars.c linux-libre-3.6.3-gnu/drivers/firmware/efivars.c
--- linux-libre-3.6-gnu/drivers/firmware/efivars.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/firmware/efivars.c	2012-10-21 12:32:56.000000000 -0400
@@ -435,12 +435,23 @@
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
-	if (var->Attributes & 0x1)
+	if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
 		str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
-	if (var->Attributes & 0x2)
+	if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
 		str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
-	if (var->Attributes & 0x4)
+	if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
 		str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
+	if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
+		str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
+	if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+		str += sprintf(str,
+			"EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
+	if (var->Attributes &
+			EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+		str += sprintf(str,
+			"EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
+	if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
+		str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
 	return str - buf;
 }
 
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-3.6.3-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/drm_crtc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/drm_crtc.c	2012-10-21 12:32:56.000000000 -0400
@@ -1034,15 +1034,15 @@
 		fb->funcs->destroy(fb);
 	}
 
-	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
-		crtc->funcs->destroy(crtc);
-	}
-
 	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
 				 head) {
 		plane->funcs->destroy(plane);
 	}
 
+	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+		crtc->funcs->destroy(crtc);
+	}
+
 	idr_remove_all(&dev->mode_config.crtc_idr);
 	idr_destroy(&dev->mode_config.crtc_idr);
 }
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/i915/i915_gem.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/i915_gem.c	2012-10-21 12:32:56.000000000 -0400
@@ -3893,7 +3893,6 @@
 
 	BUG_ON(!list_empty(&dev_priv->mm.active_list));
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
 	mutex_unlock(&dev->struct_mutex);
 
 	ret = drm_irq_install(dev);
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/i915/i915_irq.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/i915_irq.c	2012-10-21 12:32:56.000000000 -0400
@@ -680,12 +680,12 @@
 			intel_opregion_gse_intr(dev);
 
 		for (i = 0; i < 3; i++) {
+			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
+				drm_handle_vblank(dev, i);
 			if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
 				intel_prepare_page_flip(dev, i);
 				intel_finish_page_flip_plane(dev, i);
 			}
-			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
-				drm_handle_vblank(dev, i);
 		}
 
 		/* check event from PCH */
@@ -767,6 +767,12 @@
 	if (de_iir & DE_GSE)
 		intel_opregion_gse_intr(dev);
 
+	if (de_iir & DE_PIPEA_VBLANK)
+		drm_handle_vblank(dev, 0);
+
+	if (de_iir & DE_PIPEB_VBLANK)
+		drm_handle_vblank(dev, 1);
+
 	if (de_iir & DE_PLANEA_FLIP_DONE) {
 		intel_prepare_page_flip(dev, 0);
 		intel_finish_page_flip_plane(dev, 0);
@@ -777,12 +783,6 @@
 		intel_finish_page_flip_plane(dev, 1);
 	}
 
-	if (de_iir & DE_PIPEA_VBLANK)
-		drm_handle_vblank(dev, 0);
-
-	if (de_iir & DE_PIPEB_VBLANK)
-		drm_handle_vblank(dev, 1);
-
 	/* check event from PCH */
 	if (de_iir & DE_PCH_EVENT) {
 		if (pch_iir & hotplug_mask)
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.6-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-10-21 12:32:56.000000000 -0400
@@ -513,12 +513,15 @@
  */
 # define _3D_CHICKEN2_WM_READ_PIPELINED			(1 << 14)
 #define _3D_CHICKEN3	0x02090
-#define  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL		(1 << 5)
+#define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL		(1 << 5)
 
 #define MI_MODE		0x0209c
 # define VS_TIMER_DISPATCH				(1 << 6)
 # define MI_FLUSH_ENABLE				(1 << 12)
 
+#define GEN6_GT_MODE	0x20d0
+#define   GEN6_GT_MODE_HI	(1 << 9)
+
 #define GFX_MODE	0x02520
 #define GFX_MODE_GEN7	0x0229c
 #define RING_MODE_GEN7(ring)	((ring)->mmio_base+0x29c)
@@ -1753,6 +1756,10 @@
 
 /* Video Data Island Packet control */
 #define VIDEO_DIP_DATA		0x61178
+/* Read the description of VIDEO_DIP_DATA (before Haswel) or VIDEO_DIP_ECC
+ * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte
+ * of the infoframe structure specified by CEA-861. */
+#define   VIDEO_DIP_DATA_SIZE	32
 #define VIDEO_DIP_CTL		0x61170
 /* Pre HSW: */
 #define   VIDEO_DIP_ENABLE		(1 << 31)
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/i915/intel_display.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/intel_display.c	2012-10-21 12:32:56.000000000 -0400
@@ -2823,13 +2823,34 @@
 	udelay(100);
 }
 
+static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+	bool pending;
+
+	if (atomic_read(&dev_priv->mm.wedged))
+		return false;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	pending = to_intel_crtc(crtc)->unpin_work != NULL;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	return pending;
+}
+
 static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (crtc->fb == NULL)
 		return;
 
+	wait_event(dev_priv->pending_flip_queue,
+		   !intel_crtc_has_pending_flip(crtc));
+
 	mutex_lock(&dev->struct_mutex);
 	intel_finish_fb(crtc->fb);
 	mutex_unlock(&dev->struct_mutex);
@@ -4330,7 +4351,7 @@
 	/* default to 8bpc */
 	pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
 	if (is_dp) {
-		if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+		if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
 			pipeconf |= PIPECONF_BPP_6 |
 				    PIPECONF_DITHER_EN |
 				    PIPECONF_DITHER_TYPE_SP;
@@ -4684,7 +4705,7 @@
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
+	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, adjusted_mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -6149,9 +6170,8 @@
 
 	atomic_clear_mask(1 << intel_crtc->plane,
 			  &obj->pending_flip.counter);
-	if (atomic_read(&obj->pending_flip) == 0)
-		wake_up(&dev_priv->pending_flip_queue);
 
+	wake_up(&dev_priv->pending_flip_queue);
 	schedule_work(&work->work);
 
 	trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
@@ -6394,7 +6414,7 @@
 	default:
 		WARN_ONCE(1, "unknown plane in flip command\n");
 		ret = -ENODEV;
-		goto err;
+		goto err_unpin;
 	}
 
 	ret = intel_ring_begin(ring, 4);
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2012-10-21 12:32:56.000000000 -0400
@@ -151,6 +151,9 @@
 		I915_WRITE(VIDEO_DIP_DATA, *data);
 		data++;
 	}
+	/* Write every possible data byte to force correct ECC calculation. */
+	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+		I915_WRITE(VIDEO_DIP_DATA, 0);
 	mmiowb();
 
 	val |= g4x_infoframe_enable(frame);
@@ -186,6 +189,9 @@
 		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
 		data++;
 	}
+	/* Write every possible data byte to force correct ECC calculation. */
+	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
 	mmiowb();
 
 	val |= g4x_infoframe_enable(frame);
@@ -224,6 +230,9 @@
 		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
 		data++;
 	}
+	/* Write every possible data byte to force correct ECC calculation. */
+	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
 	mmiowb();
 
 	val |= g4x_infoframe_enable(frame);
@@ -259,6 +268,9 @@
 		I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
 		data++;
 	}
+	/* Write every possible data byte to force correct ECC calculation. */
+	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+		I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
 	mmiowb();
 
 	val |= g4x_infoframe_enable(frame);
@@ -292,6 +304,9 @@
 		I915_WRITE(data_reg + i, *data);
 		data++;
 	}
+	/* Write every possible data byte to force correct ECC calculation. */
+	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+		I915_WRITE(data_reg + i, 0);
 	mmiowb();
 
 	val |= hsw_infoframe_enable(frame);
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/i915/intel_pm.c linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/intel_pm.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/i915/intel_pm.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/i915/intel_pm.c	2012-10-21 12:32:56.000000000 -0400
@@ -3355,8 +3355,8 @@
 		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
 	/* Bspec says we need to always set all mask bits. */
-	I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) |
-		   _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL);
+	I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) |
+		   _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL);
 
 	/*
 	 * According to the spec the following bits should be
@@ -3387,6 +3387,11 @@
 			   DISPPLANE_TRICKLE_FEED_DISABLE);
 		intel_flush_display_plane(dev_priv, pipe);
 	}
+
+	/* The default value should be 0x200 according to docs, but the two
+	 * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */
+	I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff));
+	I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI));
 }
 
 static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c linux-libre-3.6.3-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c	2012-10-21 12:32:56.000000000 -0400
@@ -32,6 +32,7 @@
 struct nvc0_fence_priv {
 	struct nouveau_fence_priv base;
 	struct nouveau_bo *bo;
+	u32 *suspend;
 };
 
 struct nvc0_fence_chan {
@@ -125,12 +126,36 @@
 static int
 nvc0_fence_fini(struct drm_device *dev, int engine, bool suspend)
 {
+	struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO);
+	struct nvc0_fence_priv *priv = nv_engine(dev, engine);
+	int i;
+
+	if (suspend) {
+		priv->suspend = vmalloc(pfifo->channels * sizeof(u32));
+		if (!priv->suspend)
+			return -ENOMEM;
+
+		for (i = 0; i < pfifo->channels; i++)
+			priv->suspend[i] = nouveau_bo_rd32(priv->bo, i);
+	}
+
 	return 0;
 }
 
 static int
 nvc0_fence_init(struct drm_device *dev, int engine)
 {
+	struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO);
+	struct nvc0_fence_priv *priv = nv_engine(dev, engine);
+	int i;
+
+	if (priv->suspend) {
+		for (i = 0; i < pfifo->channels; i++)
+			nouveau_bo_wr32(priv->bo, i, priv->suspend[i]);
+		vfree(priv->suspend);
+		priv->suspend = NULL;
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/radeon/evergreen_cs.c linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2012-10-21 12:32:56.000000000 -0400
@@ -846,6 +846,16 @@
 		return -EINVAL;
 	}
 
+	if (!mipmap) {
+		if (llevel) {
+			dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n",
+				 __func__, __LINE__);
+			return -EINVAL;
+		} else {
+			return 0; /* everything's ok */
+		}
+	}
+
 	/* check mipmap size */
 	for (i = 1; i <= llevel; i++) {
 		unsigned w, h, d;
@@ -1081,6 +1091,27 @@
 }
 
 /**
+ * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP
+ * @p:		structure holding the parser context.
+ *
+ * Check if the next packet is a relocation packet3.
+ **/
+static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_packet p3reloc;
+	int r;
+
+	r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+	if (r) {
+		return false;
+	}
+	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+		return false;
+	}
+	return true;
+}
+
+/**
  * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:		parser structure holding parsing context.
  *
@@ -2330,7 +2361,7 @@
 		for (i = 0; i < (pkt->count / 8); i++) {
 			struct radeon_bo *texture, *mipmap;
 			u32 toffset, moffset;
-			u32 size, offset;
+			u32 size, offset, mip_address, tex_dim;
 
 			switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
 			case SQ_TEX_VTX_VALID_TEXTURE:
@@ -2359,14 +2390,28 @@
 				}
 				texture = reloc->robj;
 				toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+
 				/* tex mip base */
-				r = evergreen_cs_packet_next_reloc(p, &reloc);
-				if (r) {
-					DRM_ERROR("bad SET_RESOURCE (tex)\n");
-					return -EINVAL;
+				tex_dim = ib[idx+1+(i*8)+0] & 0x7;
+				mip_address = ib[idx+1+(i*8)+3];
+
+				if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) &&
+				    !mip_address &&
+				    !evergreen_cs_packet_next_is_pkt3_nop(p)) {
+					/* MIP_ADDRESS should point to FMASK for an MSAA texture.
+					 * It should be 0 if FMASK is disabled. */
+					moffset = 0;
+					mipmap = NULL;
+				} else {
+					r = evergreen_cs_packet_next_reloc(p, &reloc);
+					if (r) {
+						DRM_ERROR("bad SET_RESOURCE (tex)\n");
+						return -EINVAL;
+					}
+					moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+					mipmap = reloc->robj;
 				}
-				moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				mipmap = reloc->robj;
+
 				r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8));
 				if (r)
 					return r;
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/radeon/r600_cs.c linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/radeon/r600_cs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/r600_cs.c	2012-10-21 12:32:56.000000000 -0400
@@ -2180,7 +2180,8 @@
 		}
 		break;
 	case PACKET3_STRMOUT_BASE_UPDATE:
-		if (p->family < CHIP_RV770) {
+		/* RS780 and RS880 also need this */
+		if (p->family < CHIP_RS780) {
 			DRM_ERROR("STRMOUT_BASE_UPDATE only supported on 7xx\n");
 			return -EINVAL;
 		}
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2012-10-21 12:32:56.000000000 -0400
@@ -64,9 +64,11 @@
  *   2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query
  *   2.21.0 - r600-r700: FMASK and CMASK
  *   2.22.0 - r600 only: RESOLVE_BOX allowed
+ *   2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880
+ *   2.24.0 - eg only: allow MIP_ADDRESS=0 for MSAA textures
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	22
+#define KMS_DRIVER_MINOR	24
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2012-10-21 12:32:56.000000000 -0400
@@ -204,6 +204,16 @@
 	    (rdev->pdev->subsystem_device == 0x01fd))
 		return true;
 
+	/* Gateway RS690 only seems to work with MSIs. */
+	if ((rdev->pdev->device == 0x791f) &&
+	    (rdev->pdev->subsystem_vendor == 0x107b) &&
+	    (rdev->pdev->subsystem_device == 0x0185))
+		return true;
+
+	/* try and enable MSIs by default on all RS690s */
+	if (rdev->family == CHIP_RS690)
+		return true;
+
 	/* RV515 seems to have MSI issues where it loses
 	 * MSI rearms occasionally. This leads to lockups and freezes.
 	 * disable it by default.
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2012-10-21 12:32:56.000000000 -0400
@@ -974,11 +974,7 @@
 static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
-	if (tmds) {
-		if (tmds->i2c_bus)
-			radeon_i2c_destroy(tmds->i2c_bus);
-	}
+	/* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
 	kfree(radeon_encoder->enc_priv);
 	drm_encoder_cleanup(encoder);
 	kfree(radeon_encoder);
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2012-10-21 12:32:56.000000000 -0400
@@ -547,7 +547,9 @@
 void radeon_pm_resume(struct radeon_device *rdev)
 {
 	/* set up the default clocks if the MC ucode is loaded */
-	if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
+	if ((rdev->family >= CHIP_BARTS) &&
+	    (rdev->family <= CHIP_CAYMAN) &&
+	    rdev->mc_fw) {
 		if (rdev->pm.default_vddc)
 			radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
 						SET_VOLTAGE_TYPE_ASIC_VDDC);
@@ -602,7 +604,9 @@
 		radeon_pm_print_states(rdev);
 		radeon_pm_init_profile(rdev);
 		/* set up the default clocks if the MC ucode is loaded */
-		if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
+		if ((rdev->family >= CHIP_BARTS) &&
+		    (rdev->family <= CHIP_CAYMAN) &&
+		    rdev->mc_fw) {
 			if (rdev->pm.default_vddc)
 				radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
 							SET_VOLTAGE_TYPE_ASIC_VDDC);
diff -druN linux-libre-3.6-gnu/drivers/gpu/drm/savage/savage_bci.c linux-libre-3.6.3-gnu/drivers/gpu/drm/savage/savage_bci.c
--- linux-libre-3.6-gnu/drivers/gpu/drm/savage/savage_bci.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/gpu/drm/savage/savage_bci.c	2012-10-21 12:32:56.000000000 -0400
@@ -547,6 +547,8 @@
 
 	dev_priv->chipset = (enum savage_family)chipset;
 
+	pci_set_master(dev->pdev);
+
 	return 0;
 }
 
diff -druN linux-libre-3.6-gnu/drivers/hid/hid-core.c linux-libre-3.6.3-gnu/drivers/hid/hid-core.c
--- linux-libre-3.6-gnu/drivers/hid/hid-core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/hid/hid-core.c	2012-10-21 12:32:56.000000000 -0400
@@ -757,6 +757,7 @@
 	struct hid_item item;
 	unsigned int size;
 	__u8 *start;
+	__u8 *buf;
 	__u8 *end;
 	int ret;
 	static int (*dispatch_type[])(struct hid_parser *parser,
@@ -775,12 +776,21 @@
 		return -ENODEV;
 	size = device->dev_rsize;
 
+	buf = kmemdup(start, size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
 	if (device->driver->report_fixup)
-		start = device->driver->report_fixup(device, start, &size);
+		start = device->driver->report_fixup(device, buf, &size);
+	else
+		start = buf;
 
-	device->rdesc = kmemdup(start, size, GFP_KERNEL);
-	if (device->rdesc == NULL)
+	start = kmemdup(start, size, GFP_KERNEL);
+	kfree(buf);
+	if (start == NULL)
 		return -ENOMEM;
+
+	device->rdesc = start;
 	device->rsize = size;
 
 	parser = vzalloc(sizeof(struct hid_parser));
diff -druN linux-libre-3.6-gnu/drivers/hid/hidraw.c linux-libre-3.6.3-gnu/drivers/hid/hidraw.c
--- linux-libre-3.6-gnu/drivers/hid/hidraw.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/hid/hidraw.c	2012-10-21 12:32:56.000000000 -0400
@@ -42,6 +42,7 @@
 static struct class *hidraw_class;
 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
 static DEFINE_MUTEX(minors_lock);
+static void drop_ref(struct hidraw *hid, int exists_bit);
 
 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
@@ -113,7 +114,7 @@
 	__u8 *buf;
 	int ret = 0;
 
-	if (!hidraw_table[minor]) {
+	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 		ret = -ENODEV;
 		goto out;
 	}
@@ -261,7 +262,7 @@
 	}
 
 	mutex_lock(&minors_lock);
-	if (!hidraw_table[minor]) {
+	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 		err = -ENODEV;
 		goto out_unlock;
 	}
@@ -298,36 +299,12 @@
 static int hidraw_release(struct inode * inode, struct file * file)
 {
 	unsigned int minor = iminor(inode);
-	struct hidraw *dev;
 	struct hidraw_list *list = file->private_data;
-	int ret;
-	int i;
-
-	mutex_lock(&minors_lock);
-	if (!hidraw_table[minor]) {
-		ret = -ENODEV;
-		goto unlock;
-	}
 
+	drop_ref(hidraw_table[minor], 0);
 	list_del(&list->node);
-	dev = hidraw_table[minor];
-	if (!--dev->open) {
-		if (list->hidraw->exist) {
-			hid_hw_power(dev->hid, PM_HINT_NORMAL);
-			hid_hw_close(dev->hid);
-		} else {
-			kfree(list->hidraw);
-		}
-	}
-
-	for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
-		kfree(list->buffer[i].value);
 	kfree(list);
-	ret = 0;
-unlock:
-	mutex_unlock(&minors_lock);
-
-	return ret;
+	return 0;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -529,21 +506,7 @@
 void hidraw_disconnect(struct hid_device *hid)
 {
 	struct hidraw *hidraw = hid->hidraw;
-
-	mutex_lock(&minors_lock);
-	hidraw->exist = 0;
-
-	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-
-	hidraw_table[hidraw->minor] = NULL;
-
-	if (hidraw->open) {
-		hid_hw_close(hid);
-		wake_up_interruptible(&hidraw->wait);
-	} else {
-		kfree(hidraw);
-	}
-	mutex_unlock(&minors_lock);
+	drop_ref(hidraw, 1);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 
@@ -585,3 +548,23 @@
 	unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
 
 }
+
+static void drop_ref(struct hidraw *hidraw, int exists_bit)
+{
+	mutex_lock(&minors_lock);
+	if (exists_bit) {
+		hid_hw_close(hidraw->hid);
+		hidraw->exist = 0;
+		if (hidraw->open)
+			wake_up_interruptible(&hidraw->wait);
+	} else {
+		--hidraw->open;
+	}
+
+	if (!hidraw->open && !hidraw->exist) {
+		device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+		hidraw_table[hidraw->minor] = NULL;
+		kfree(hidraw);
+	}
+	mutex_unlock(&minors_lock);
+}
diff -druN linux-libre-3.6-gnu/drivers/hid/usbhid/hid-core.c linux-libre-3.6.3-gnu/drivers/hid/usbhid/hid-core.c
--- linux-libre-3.6-gnu/drivers/hid/usbhid/hid-core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/hid/usbhid/hid-core.c	2012-10-21 12:32:56.000000000 -0400
@@ -1415,20 +1415,20 @@
 	 * configuration descriptors passed, we already know that
 	 * the size of the HID report descriptor has not changed.
 	 */
-	rdesc = kmalloc(hid->rsize, GFP_KERNEL);
+	rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL);
 	if (!rdesc) {
 		dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
 		return 1;
 	}
 	status = hid_get_class_descriptor(dev,
 				interface->desc.bInterfaceNumber,
-				HID_DT_REPORT, rdesc, hid->rsize);
+				HID_DT_REPORT, rdesc, hid->dev_rsize);
 	if (status < 0) {
 		dbg_hid("reading report descriptor failed (post_reset)\n");
 		kfree(rdesc);
 		return 1;
 	}
-	status = memcmp(rdesc, hid->rdesc, hid->rsize);
+	status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize);
 	kfree(rdesc);
 	if (status != 0) {
 		dbg_hid("report descriptor changed\n");
diff -druN linux-libre-3.6-gnu/drivers/i2c/busses/i2c-piix4.c linux-libre-3.6.3-gnu/drivers/i2c/busses/i2c-piix4.c
--- linux-libre-3.6-gnu/drivers/i2c/busses/i2c-piix4.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/i2c/busses/i2c-piix4.c	2012-10-21 12:32:56.000000000 -0400
@@ -37,6 +37,7 @@
 #include <linux/stddef.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
 #include <linux/acpi.h>
diff -druN linux-libre-3.6-gnu/drivers/infiniband/hw/qib/qib_keys.c linux-libre-3.6.3-gnu/drivers/infiniband/hw/qib/qib_keys.c
--- linux-libre-3.6-gnu/drivers/infiniband/hw/qib/qib_keys.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/infiniband/hw/qib/qib_keys.c	2012-10-21 12:32:56.000000000 -0400
@@ -186,8 +186,9 @@
 		goto bail;
 
 	off = sge->addr - mr->user_base;
-	if (unlikely(sge->addr < mr->iova || off + sge->length > mr->length ||
-		     (mr->access_flags & acc) == 0))
+	if (unlikely(sge->addr < mr->user_base ||
+		     off + sge->length > mr->length ||
+		     (mr->access_flags & acc) != acc))
 		goto bail;
 	if (unlikely(!atomic_inc_not_zero(&mr->refcount)))
 		goto bail;
diff -druN linux-libre-3.6-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-3.6.3-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-3.6-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2012-10-21 12:32:56.000000000 -0400
@@ -150,7 +150,7 @@
 
 	netif_stop_queue(dev);
 
-	ipoib_ib_dev_down(dev, 0);
+	ipoib_ib_dev_down(dev, 1);
 	ipoib_ib_dev_stop(dev, 0);
 
 	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
diff -druN linux-libre-3.6-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-3.6.3-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- linux-libre-3.6-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2012-10-21 12:32:56.000000000 -0400
@@ -175,7 +175,9 @@
 
 	mcast->mcmember = *mcmember;
 
-	/* Set the cached Q_Key before we attach if it's the broadcast group */
+	/* Set the multicast MTU and cached Q_Key before we attach if it's
+	 * the broadcast group.
+	 */
 	if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
 		    sizeof (union ib_gid))) {
 		spin_lock_irq(&priv->lock);
@@ -183,10 +185,17 @@
 			spin_unlock_irq(&priv->lock);
 			return -EAGAIN;
 		}
+		priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
 		priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
 		spin_unlock_irq(&priv->lock);
 		priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
 		set_qkey = 1;
+
+		if (!ipoib_cm_admin_enabled(dev)) {
+			rtnl_lock();
+			dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
+			rtnl_unlock();
+		}
 	}
 
 	if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
@@ -574,14 +583,6 @@
 		return;
 	}
 
-	priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
-
-	if (!ipoib_cm_admin_enabled(dev)) {
-		rtnl_lock();
-		dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
-		rtnl_unlock();
-	}
-
 	ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
 
 	clear_bit(IPOIB_MCAST_RUN, &priv->flags);
diff -druN linux-libre-3.6-gnu/drivers/infiniband/ulp/srp/ib_srp.c linux-libre-3.6.3-gnu/drivers/infiniband/ulp/srp/ib_srp.c
--- linux-libre-3.6-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2012-10-21 12:32:56.000000000 -0400
@@ -638,9 +638,9 @@
 	struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL);
 
 	if (scmnd) {
+		srp_free_req(target, req, scmnd, 0);
 		scmnd->result = DID_RESET << 16;
 		scmnd->scsi_done(scmnd);
-		srp_free_req(target, req, scmnd, 0);
 	}
 }
 
@@ -1687,6 +1687,7 @@
 			  SRP_TSK_ABORT_TASK);
 	srp_free_req(target, req, scmnd, 0);
 	scmnd->result = DID_ABORT << 16;
+	scmnd->scsi_done(scmnd);
 
 	return SUCCESS;
 }
diff -druN linux-libre-3.6-gnu/drivers/input/mouse/synaptics.c linux-libre-3.6.3-gnu/drivers/input/mouse/synaptics.c
--- linux-libre-3.6-gnu/drivers/input/mouse/synaptics.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/input/mouse/synaptics.c	2012-10-21 12:32:56.000000000 -0400
@@ -53,14 +53,19 @@
 #define ABS_POS_BITS 13
 
 /*
- * Any position values from the hardware above the following limits are
- * treated as "wrapped around negative" values that have been truncated to
- * the 13-bit reporting range of the hardware. These are just reasonable
- * guesses and can be adjusted if hardware is found that operates outside
- * of these parameters.
+ * These values should represent the absolute maximum value that will
+ * be reported for a positive position value. Some Synaptics firmware
+ * uses this value to indicate a finger near the edge of the touchpad
+ * whose precise position cannot be determined.
+ *
+ * At least one touchpad is known to report positions in excess of this
+ * value which are actually negative values truncated to the 13-bit
+ * reporting range. These values have never been observed to be lower
+ * than 8184 (i.e. -8), so we treat all values greater than 8176 as
+ * negative and any other value as positive.
  */
-#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2)
-#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2)
+#define X_MAX_POSITIVE 8176
+#define Y_MAX_POSITIVE 8176
 
 /*****************************************************************************
  *	Stuff we need even when we do not want native Synaptics support
@@ -604,11 +609,21 @@
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 	}
 
-	/* Convert wrap-around values to negative */
+	/*
+	 * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
+	 * is used by some firmware to indicate a finger at the edge of
+	 * the touchpad whose precise position cannot be determined, so
+	 * convert these values to the maximum axis value.
+	 */
 	if (hw->x > X_MAX_POSITIVE)
 		hw->x -= 1 << ABS_POS_BITS;
+	else if (hw->x == X_MAX_POSITIVE)
+		hw->x = XMAX;
+
 	if (hw->y > Y_MAX_POSITIVE)
 		hw->y -= 1 << ABS_POS_BITS;
+	else if (hw->y == Y_MAX_POSITIVE)
+		hw->y = YMAX;
 
 	return 0;
 }
diff -druN linux-libre-3.6-gnu/drivers/iommu/intel-iommu.c linux-libre-3.6.3-gnu/drivers/iommu/intel-iommu.c
--- linux-libre-3.6-gnu/drivers/iommu/intel-iommu.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/iommu/intel-iommu.c	2012-10-21 12:32:56.000000000 -0400
@@ -589,7 +589,9 @@
 {
 	int i;
 
-	domain->iommu_coherency = 1;
+	i = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
+
+	domain->iommu_coherency = i < g_num_of_iommus ? 1 : 0;
 
 	for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
 		if (!ecap_coherent(g_iommus[i]->ecap)) {
diff -druN linux-libre-3.6-gnu/drivers/md/raid10.c linux-libre-3.6.3-gnu/drivers/md/raid10.c
--- linux-libre-3.6-gnu/drivers/md/raid10.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/md/raid10.c	2012-10-21 12:32:56.000000000 -0400
@@ -3158,7 +3158,7 @@
 				else {
 					bad_sectors -= (sector - first_bad);
 					if (max_sync > bad_sectors)
-						max_sync = max_sync;
+						max_sync = bad_sectors;
 					continue;
 				}
 			}
diff -druN linux-libre-3.6-gnu/drivers/media/dvb/frontends/drxk.h linux-libre-3.6.3-gnu/drivers/media/dvb/frontends/drxk.h
--- linux-libre-3.6-gnu/drivers/media/dvb/frontends/drxk.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/media/dvb/frontends/drxk.h	2012-10-21 12:32:56.000000000 -0400
@@ -28,6 +28,7 @@
  *				A value of 0 (default) or lower indicates that
  *				the correct number of parameters will be
  *				automatically detected.
+ * @load_firmware_sync:		Force the firmware load to be synchronous.
  *
  * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
  * UIO-3.
@@ -39,6 +40,7 @@
 	bool	parallel_ts;
 	bool	dynamic_clk;
 	bool	enable_merr_cfg;
+	bool	load_firmware_sync;
 
 	bool	antenna_dvbt;
 	u16	antenna_gpio;
diff -druN linux-libre-3.6-gnu/drivers/media/dvb/frontends/drxk_hard.c linux-libre-3.6.3-gnu/drivers/media/dvb/frontends/drxk_hard.c
--- linux-libre-3.6-gnu/drivers/media/dvb/frontends/drxk_hard.c	2012-09-30 20:53:14.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/media/dvb/frontends/drxk_hard.c	2012-10-21 13:54:16.000000000 -0400
@@ -6609,15 +6609,25 @@
 
 	/* Load firmware and initialize DRX-K */
 	if (state->microcode_name) {
-		status = reject_firmware_nowait(THIS_MODULE, 1,
+		if (config->load_firmware_sync) {
+			const struct firmware *fw = NULL;
+
+			status = reject_firmware(&fw, state->microcode_name,
+						  state->i2c->dev.parent);
+			if (status < 0)
+				fw = NULL;
+			load_firmware_cb(fw, state);
+		} else {
+			status = reject_firmware_nowait(THIS_MODULE, 1,
 					      state->microcode_name,
 					      state->i2c->dev.parent,
 					      GFP_KERNEL,
 					      state, load_firmware_cb);
-		if (status < 0) {
-			printk(KERN_ERR
-			"drxk: failed to request a firmware\n");
-			return NULL;
+			if (status < 0) {
+				printk(KERN_ERR
+				       "drxk: failed to request a firmware\n");
+				return NULL;
+			}
 		}
 	} else if (init_drxk(state) < 0)
 		goto error;
diff -druN linux-libre-3.6-gnu/drivers/media/rc/ite-cir.c linux-libre-3.6.3-gnu/drivers/media/rc/ite-cir.c
--- linux-libre-3.6-gnu/drivers/media/rc/ite-cir.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/media/rc/ite-cir.c	2012-10-21 12:32:56.000000000 -0400
@@ -1473,6 +1473,7 @@
 	rdev = rc_allocate_device();
 	if (!rdev)
 		goto failure;
+	itdev->rdev = rdev;
 
 	ret = -ENODEV;
 
@@ -1604,7 +1605,6 @@
 	if (ret)
 		goto failure3;
 
-	itdev->rdev = rdev;
 	ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
 
 	return 0;
diff -druN linux-libre-3.6-gnu/drivers/media/video/em28xx/em28xx-cards.c linux-libre-3.6.3-gnu/drivers/media/video/em28xx/em28xx-cards.c
--- linux-libre-3.6-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-09-30 20:51:37.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-10-21 13:51:43.000000000 -0400
@@ -2875,12 +2875,20 @@
 }
 
 
-#if defined(CONFIG_MODULES) && defined(MODULE)
 static void request_module_async(struct work_struct *work)
 {
 	struct em28xx *dev = container_of(work,
 			     struct em28xx, request_module_wk);
 
+	/*
+	 * The em28xx extensions can be modules or builtin. If the
+	 * modules are already loaded or are built in, those extensions
+	 * can be initialised right now. Otherwise, the module init
+	 * code will do it.
+	 */
+	em28xx_init_extension(dev);
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
 	if (dev->has_audio_class)
 		request_module("snd-usb-audio");
 	else if (dev->has_alsa_audio)
@@ -2890,6 +2898,7 @@
 		request_module("em28xx-dvb");
 	if (dev->board.ir_codes && !disable_ir)
 		request_module("em28xx-rc");
+#endif /* CONFIG_MODULES */
 }
 
 static void request_modules(struct em28xx *dev)
@@ -2902,10 +2911,6 @@
 {
 	flush_work_sync(&dev->request_module_wk);
 }
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
 
 /*
  * em28xx_release_resources()
@@ -3324,13 +3329,6 @@
 	 */
 	mutex_unlock(&dev->lock);
 
-	/*
-	 * These extensions can be modules. If the modules are already
-	 * loaded then we can initialise the device now, otherwise we
-	 * will initialise it when the modules load instead.
-	 */
-	em28xx_init_extension(dev);
-
 	return 0;
 
 unlock_and_free:
diff -druN linux-libre-3.6-gnu/drivers/media/video/em28xx/em28xx-dvb.c linux-libre-3.6.3-gnu/drivers/media/video/em28xx/em28xx-dvb.c
--- linux-libre-3.6-gnu/drivers/media/video/em28xx/em28xx-dvb.c	2012-09-30 20:54:00.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/media/video/em28xx/em28xx-dvb.c	2012-10-21 13:55:36.000000000 -0400
@@ -316,6 +316,7 @@
 	.no_i2c_bridge = 1,
 	.microcode_name = "/*(DEBLOBBED)*/",
 	.qam_demod_parameter_count = 2,
+	.load_firmware_sync = true,
 };
 
 static struct drxk_config hauppauge_930c_drxk = {
@@ -325,6 +326,7 @@
 	.microcode_name = "/*(DEBLOBBED)*/",
 	.chunk_size = 56,
 	.qam_demod_parameter_count = 2,
+	.load_firmware_sync = true,
 };
 
 struct drxk_config terratec_htc_stick_drxk = {
@@ -338,12 +340,14 @@
 	.antenna_dvbt = true,
 	/* The windows driver uses the same. This will disable LNA. */
 	.antenna_gpio = 0x6,
+	.load_firmware_sync = true,
 };
 
 static struct drxk_config maxmedia_ub425_tc_drxk = {
 	.adr = 0x29,
 	.single_master = 1,
 	.no_i2c_bridge = 1,
+	.load_firmware_sync = true,
 };
 
 static struct drxk_config pctv_520e_drxk = {
@@ -354,6 +358,7 @@
 	.chunk_size = 58,
 	.antenna_dvbt = true, /* disable LNA */
 	.antenna_gpio = (1 << 2), /* disable LNA */
+	.load_firmware_sync = true,
 };
 
 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
diff -druN linux-libre-3.6-gnu/drivers/media/video/gspca/pac7302.c linux-libre-3.6.3-gnu/drivers/media/video/gspca/pac7302.c
--- linux-libre-3.6-gnu/drivers/media/video/gspca/pac7302.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/media/video/gspca/pac7302.c	2012-10-21 12:32:56.000000000 -0400
@@ -616,7 +616,7 @@
 	sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 					V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
 	sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-					V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
+					V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1);
 
 	gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 					V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -905,6 +905,7 @@
 	{USB_DEVICE(0x093a, 0x262a)},
 	{USB_DEVICE(0x093a, 0x262c)},
 	{USB_DEVICE(0x145f, 0x013c)},
+	{USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
diff -druN linux-libre-3.6-gnu/drivers/mfd/88pm860x-core.c linux-libre-3.6.3-gnu/drivers/mfd/88pm860x-core.c
--- linux-libre-3.6-gnu/drivers/mfd/88pm860x-core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mfd/88pm860x-core.c	2012-10-21 12:32:56.000000000 -0400
@@ -21,40 +21,73 @@
 
 #define INT_STATUS_NUM			3
 
+static struct resource io_parent = {
+	.start = 0,
+	.end   = 0xffffffff,
+	.flags = IORESOURCE_IO,
+};
+
 static struct resource bk_resources[] __devinitdata = {
-	{PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
-	{PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
-	{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
+	{PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,
+	 &io_parent,},
 };
 
 static struct resource led_resources[] __devinitdata = {
-	{PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,},
-	{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
-	{PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,},
-	{PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_IO,},
-	{PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,},
-	{PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,},
+	{PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,
+	 &io_parent,},
 };
 
 static struct resource regulator_resources[] __devinitdata = {
-	{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
-	{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
-	{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
-	{PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_IO,},
-	{PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_IO,},
-	{PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_IO,},
-	{PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_IO,},
-	{PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_IO,},
-	{PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_IO,},
-	{PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_IO,},
-	{PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_IO,},
-	{PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_IO,},
-	{PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,},
-	{PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,},
-	{PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,},
-	{PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,},
-	{PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,},
-	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
+	{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,
+	 &io_parent,},
+	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,
+	 &io_parent,},
 };
 
 static struct resource touch_resources[] __devinitdata = {
@@ -91,11 +124,12 @@
 };
 
 static struct resource preg_resources[] __devinitdata = {
-	{PM8606_ID_PREG,  PM8606_ID_PREG,  "preg",   IORESOURCE_IO,},
+	{PM8606_ID_PREG,  PM8606_ID_PREG,  "preg",   IORESOURCE_IO,
+	 &io_parent,},
 };
 
 static struct resource rtc_resources[] __devinitdata = {
-	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
+	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ, &io_parent,},
 };
 
 static struct mfd_cell bk_devs[] = {
diff -druN linux-libre-3.6-gnu/drivers/mfd/max8925-core.c linux-libre-3.6.3-gnu/drivers/mfd/max8925-core.c
--- linux-libre-3.6-gnu/drivers/mfd/max8925-core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mfd/max8925-core.c	2012-10-21 12:32:56.000000000 -0400
@@ -18,12 +18,19 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
 
+static struct resource io_parent = {
+	.start = 0,
+	.end   = 0xffffffff,
+	.flags = IORESOURCE_IO,
+};
+
 static struct resource backlight_resources[] = {
 	{
 		.name	= "max8925-backlight",
 		.start	= MAX8925_WLED_MODE_CNTL,
 		.end	= MAX8925_WLED_CNTL,
 		.flags	= IORESOURCE_IO,
+		.parent = &io_parent,
 	},
 };
 
@@ -42,6 +49,7 @@
 		.start	= MAX8925_TSC_IRQ,
 		.end	= MAX8925_ADC_RES_END,
 		.flags	= IORESOURCE_IO,
+		.parent = &io_parent,
 	},
 };
 
@@ -60,6 +68,7 @@
 		.start	= MAX8925_CHG_IRQ1,
 		.end	= MAX8925_CHG_IRQ1_MASK,
 		.flags	= IORESOURCE_IO,
+		.parent = &io_parent,
 	},
 };
 
@@ -118,6 +127,7 @@
 	.start	= MAX8925_##_start,		\
 	.end	= MAX8925_##_end,		\
 	.flags	= IORESOURCE_IO,		\
+	.parent = &io_parent,			\
 }
 
 static struct resource regulator_resources[] = {
diff -druN linux-libre-3.6-gnu/drivers/mmc/core/slot-gpio.c linux-libre-3.6.3-gnu/drivers/mmc/core/slot-gpio.c
--- linux-libre-3.6-gnu/drivers/mmc/core/slot-gpio.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mmc/core/slot-gpio.c	2012-10-21 12:32:56.000000000 -0400
@@ -100,7 +100,13 @@
 
 	ctx = host->slot.handler_priv;
 
-	return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+	ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+	if (ret < 0)
+		return ret;
+
+	ctx->ro_gpio = gpio;
+
+	return 0;
 }
 EXPORT_SYMBOL(mmc_gpio_request_ro);
 
diff -druN linux-libre-3.6-gnu/drivers/mmc/host/omap_hsmmc.c linux-libre-3.6.3-gnu/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-3.6-gnu/drivers/mmc/host/omap_hsmmc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mmc/host/omap_hsmmc.c	2012-10-21 12:32:56.000000000 -0400
@@ -2106,8 +2106,7 @@
 	if (ret) {
 		host->suspended = 0;
 		if (host->pdata->resume) {
-			ret = host->pdata->resume(dev, host->slot_id);
-			if (ret)
+			if (host->pdata->resume(dev, host->slot_id))
 				dev_dbg(dev, "Unmask interrupt failed\n");
 		}
 		goto err;
diff -druN linux-libre-3.6-gnu/drivers/mmc/host/sh_mmcif.c linux-libre-3.6.3-gnu/drivers/mmc/host/sh_mmcif.c
--- linux-libre-3.6-gnu/drivers/mmc/host/sh_mmcif.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mmc/host/sh_mmcif.c	2012-10-21 12:32:56.000000000 -0400
@@ -1229,6 +1229,10 @@
 		host->sd_error = true;
 		dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
 	}
+	if (host->state == STATE_IDLE) {
+		dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state);
+		return IRQ_HANDLED;
+	}
 	if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
 		if (!host->dma_active)
 			return IRQ_WAKE_THREAD;
diff -druN linux-libre-3.6-gnu/drivers/mtd/maps/autcpu12-nvram.c linux-libre-3.6.3-gnu/drivers/mtd/maps/autcpu12-nvram.c
--- linux-libre-3.6-gnu/drivers/mtd/maps/autcpu12-nvram.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/maps/autcpu12-nvram.c	2012-10-21 12:32:56.000000000 -0400
@@ -43,7 +43,8 @@
 
 static int __init init_autcpu12_sram (void)
 {
-	int err, save0, save1;
+	map_word tmp, save0, save1;
+	int err;
 
 	autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K);
 	if (!autcpu12_sram_map.virt) {
@@ -51,7 +52,7 @@
 		err = -EIO;
 		goto out;
 	}
-	simple_map_init(&autcpu_sram_map);
+	simple_map_init(&autcpu12_sram_map);
 
 	/*
 	 * Check for 32K/128K
@@ -61,20 +62,22 @@
 	 * Read	and check result on ofs 0x0
 	 * Restore contents
 	 */
-	save0 = map_read32(&autcpu12_sram_map,0);
-	save1 = map_read32(&autcpu12_sram_map,0x10000);
-	map_write32(&autcpu12_sram_map,~save0,0x10000);
+	save0 = map_read(&autcpu12_sram_map, 0);
+	save1 = map_read(&autcpu12_sram_map, 0x10000);
+	tmp.x[0] = ~save0.x[0];
+	map_write(&autcpu12_sram_map, tmp, 0x10000);
 	/* if we find this pattern on 0x0, we have 32K size
 	 * restore contents and exit
 	 */
-	if ( map_read32(&autcpu12_sram_map,0) != save0) {
-		map_write32(&autcpu12_sram_map,save0,0x0);
+	tmp = map_read(&autcpu12_sram_map, 0);
+	if (!map_word_equal(&autcpu12_sram_map, tmp, save0)) {
+		map_write(&autcpu12_sram_map, save0, 0x0);
 		goto map;
 	}
 	/* We have a 128K found, restore 0x10000 and set size
 	 * to 128K
 	 */
-	map_write32(&autcpu12_sram_map,save1,0x10000);
+	map_write(&autcpu12_sram_map, save1, 0x10000);
 	autcpu12_sram_map.size = SZ_128K;
 
 map:
diff -druN linux-libre-3.6-gnu/drivers/mtd/mtdpart.c linux-libre-3.6.3-gnu/drivers/mtd/mtdpart.c
--- linux-libre-3.6-gnu/drivers/mtd/mtdpart.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/mtdpart.c	2012-10-21 12:32:56.000000000 -0400
@@ -711,6 +711,8 @@
  * partition parsers, specified in @types. However, if @types is %NULL, then
  * the default list of parsers is used. The default list contains only the
  * "cmdlinepart" and "ofpart" parsers ATM.
+ * Note: If there are more then one parser in @types, the kernel only takes the
+ * partitions parsed out by the first parser.
  *
  * This function may return:
  * o a negative error code in case of failure
@@ -735,11 +737,12 @@
 		if (!parser)
 			continue;
 		ret = (*parser->parse_fn)(master, pparts, data);
+		put_partition_parser(parser);
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			       ret, parser->name, master->name);
+			break;
 		}
-		put_partition_parser(parser);
 	}
 	return ret;
 }
diff -druN linux-libre-3.6-gnu/drivers/mtd/nand/nand_base.c linux-libre-3.6.3-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-3.6-gnu/drivers/mtd/nand/nand_base.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/nand/nand_base.c	2012-10-21 12:32:56.000000000 -0400
@@ -2914,8 +2914,7 @@
 	if (le16_to_cpu(p->features) & 1)
 		*busw = NAND_BUSWIDTH_16;
 
-	chip->options &= ~NAND_CHIPOPTIONS_MSK;
-	chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK;
+	chip->options |= NAND_NO_READRDY;
 
 	pr_info("ONFI flash detected\n");
 	return 1;
@@ -3080,9 +3079,8 @@
 			mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
 		}
 	}
-	/* Get chip options, preserve non chip based options */
-	chip->options &= ~NAND_CHIPOPTIONS_MSK;
-	chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
+	/* Get chip options */
+	chip->options |= type->options;
 
 	/*
 	 * Check if chip is not a Samsung device. Do not clear the
diff -druN linux-libre-3.6-gnu/drivers/mtd/nand/nand_bbt.c linux-libre-3.6.3-gnu/drivers/mtd/nand/nand_bbt.c
--- linux-libre-3.6-gnu/drivers/mtd/nand/nand_bbt.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/nand/nand_bbt.c	2012-10-21 12:32:56.000000000 -0400
@@ -390,7 +390,7 @@
 	/* Read the mirror version, if available */
 	if (md && (md->options & NAND_BBT_VERSION)) {
 		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
-			      mtd->writesize, td);
+			      mtd->writesize, md);
 		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
 		pr_info("Bad block table at page %d, version 0x%02X\n",
 			 md->pages[0], md->version[0]);
diff -druN linux-libre-3.6-gnu/drivers/mtd/nand/nandsim.c linux-libre-3.6.3-gnu/drivers/mtd/nand/nandsim.c
--- linux-libre-3.6-gnu/drivers/mtd/nand/nandsim.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/nand/nandsim.c	2012-10-21 12:32:56.000000000 -0400
@@ -2333,6 +2333,7 @@
 		uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize;
 		if (new_size >> overridesize != nsmtd->erasesize) {
 			NS_ERR("overridesize is too big\n");
+			retval = -EINVAL;
 			goto err_exit;
 		}
 		/* N.B. This relies on nand_scan not doing anything with the size before we change it */
diff -druN linux-libre-3.6-gnu/drivers/mtd/nand/omap2.c linux-libre-3.6.3-gnu/drivers/mtd/nand/omap2.c
--- linux-libre-3.6-gnu/drivers/mtd/nand/omap2.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/nand/omap2.c	2012-10-21 12:32:56.000000000 -0400
@@ -1387,7 +1387,8 @@
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
 	iounmap(info->nand.IO_ADDR_R);
-	kfree(&info->mtd);
+	release_mem_region(info->phys_base, NAND_IO_SIZE);
+	kfree(info);
 	return 0;
 }
 
diff -druN linux-libre-3.6-gnu/drivers/mtd/ubi/attach.c linux-libre-3.6.3-gnu/drivers/mtd/ubi/attach.c
--- linux-libre-3.6-gnu/drivers/mtd/ubi/attach.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/ubi/attach.c	2012-10-21 12:32:56.000000000 -0400
@@ -975,7 +975,7 @@
 			return err;
 		goto adjust_mean_ec;
 	case UBI_IO_FF:
-		if (ec_err)
+		if (ec_err || bitflips)
 			err = add_to_list(ai, pnum, UBI_UNKNOWN,
 					  UBI_UNKNOWN, ec, 1, &ai->erase);
 		else
diff -druN linux-libre-3.6-gnu/drivers/mtd/ubi/build.c linux-libre-3.6.3-gnu/drivers/mtd/ubi/build.c
--- linux-libre-3.6-gnu/drivers/mtd/ubi/build.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/mtd/ubi/build.c	2012-10-21 12:32:56.000000000 -0400
@@ -759,6 +759,11 @@
 	struct ubi_volume *vol = ubi->volumes[vol_id];
 	int err, old_reserved_pebs = vol->reserved_pebs;
 
+	if (ubi->ro_mode) {
+		ubi_warn("skip auto-resize because of R/O mode");
+		return 0;
+	}
+
 	/*
 	 * Clear the auto-resize flag in the volume in-memory copy of the
 	 * volume table, and 'ubi_resize_volume()' will propagate this change
diff -druN linux-libre-3.6-gnu/drivers/net/can/mscan/mpc5xxx_can.c linux-libre-3.6.3-gnu/drivers/net/can/mscan/mpc5xxx_can.c
--- linux-libre-3.6-gnu/drivers/net/can/mscan/mpc5xxx_can.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/can/mscan/mpc5xxx_can.c	2012-10-21 12:32:56.000000000 -0400
@@ -181,7 +181,7 @@
 
 		if (!clock_name || !strcmp(clock_name, "sys")) {
 			sys_clk = clk_get(&ofdev->dev, "sys_clk");
-			if (!sys_clk) {
+			if (IS_ERR(sys_clk)) {
 				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
 				goto exit_unmap;
 			}
@@ -204,7 +204,7 @@
 
 		if (clocksrc < 0) {
 			ref_clk = clk_get(&ofdev->dev, "ref_clk");
-			if (!ref_clk) {
+			if (IS_ERR(ref_clk)) {
 				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
 				goto exit_unmap;
 			}
diff -druN linux-libre-3.6-gnu/drivers/net/ethernet/intel/e1000e/e1000.h linux-libre-3.6.3-gnu/drivers/net/ethernet/intel/e1000e/e1000.h
--- linux-libre-3.6-gnu/drivers/net/ethernet/intel/e1000e/e1000.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/ethernet/intel/e1000e/e1000.h	2012-10-21 12:32:56.000000000 -0400
@@ -175,13 +175,13 @@
 /*
  * in the case of WTHRESH, it appears at least the 82571/2 hardware
  * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
- * WTHRESH=4, and since we want 64 bytes at a time written back, set
- * it to 5
+ * WTHRESH=4, so a setting of 5 gives the most efficient bus
+ * utilization but to avoid possible Tx stalls, set it to 1
  */
 #define E1000_TXDCTL_DMA_BURST_ENABLE                          \
 	(E1000_TXDCTL_GRAN | /* set descriptor granularity */  \
 	 E1000_TXDCTL_COUNT_DESC |                             \
-	 (5 << 16) | /* wthresh must be +1 more than desired */\
+	 (1 << 16) | /* wthresh must be +1 more than desired */\
 	 (1 << 8)  | /* hthresh */                             \
 	 0x1f)       /* pthresh */
 
diff -druN linux-libre-3.6-gnu/drivers/net/ethernet/intel/e1000e/netdev.c linux-libre-3.6.3-gnu/drivers/net/ethernet/intel/e1000e/netdev.c
--- linux-libre-3.6-gnu/drivers/net/ethernet/intel/e1000e/netdev.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/ethernet/intel/e1000e/netdev.c	2012-10-21 12:32:56.000000000 -0400
@@ -2831,7 +2831,7 @@
 		 * set up some performance related parameters to encourage the
 		 * hardware to use the bus more efficiently in bursts, depends
 		 * on the tx_int_delay to be enabled,
-		 * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
+		 * wthresh = 1 ==> burst write is disabled to avoid Tx stalls
 		 * hthresh = 1 ==> prefetch when one or more available
 		 * pthresh = 0x1f ==> prefetch if internal cache 31 or less
 		 * BEWARE: this seems to work but should be considered first if
diff -druN linux-libre-3.6-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c linux-libre-3.6.3-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
--- linux-libre-3.6-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c	2012-10-21 12:32:56.000000000 -0400
@@ -2690,10 +2690,7 @@
 			(1 << HWTSTAMP_FILTER_NONE) |
 			(1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
 			(1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
-			(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
-			(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
-			(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
-			(1 << HWTSTAMP_FILTER_SOME);
+			(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
 		break;
 #endif /* CONFIG_IXGBE_PTP */
 	default:
diff -druN linux-libre-3.6-gnu/drivers/net/ethernet/ti/davinci_cpdma.c linux-libre-3.6.3-gnu/drivers/net/ethernet/ti/davinci_cpdma.c
--- linux-libre-3.6-gnu/drivers/net/ethernet/ti/davinci_cpdma.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/ethernet/ti/davinci_cpdma.c	2012-10-21 12:32:56.000000000 -0400
@@ -863,6 +863,7 @@
 
 		next_dma = desc_read(desc, hw_next);
 		chan->head = desc_from_phys(pool, next_dma);
+		chan->count--;
 		chan->stats.teardown_dequeue++;
 
 		/* issue callback without locks held */
diff -druN linux-libre-3.6-gnu/drivers/net/rionet.c linux-libre-3.6.3-gnu/drivers/net/rionet.c
--- linux-libre-3.6-gnu/drivers/net/rionet.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/rionet.c	2012-10-21 12:32:56.000000000 -0400
@@ -79,6 +79,7 @@
  * on system trade-offs.
  */
 static struct rio_dev **rionet_active;
+static int nact;	/* total number of active rionet peers */
 
 #define is_rionet_capable(src_ops, dst_ops)			\
 			((src_ops & RIO_SRC_OPS_DATA_MSG) &&	\
@@ -175,6 +176,7 @@
 	struct ethhdr *eth = (struct ethhdr *)skb->data;
 	u16 destid;
 	unsigned long flags;
+	int add_num = 1;
 
 	local_irq_save(flags);
 	if (!spin_trylock(&rnet->tx_lock)) {
@@ -182,7 +184,10 @@
 		return NETDEV_TX_LOCKED;
 	}
 
-	if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+	if (is_multicast_ether_addr(eth->h_dest))
+		add_num = nact;
+
+	if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
 		netif_stop_queue(ndev);
 		spin_unlock_irqrestore(&rnet->tx_lock, flags);
 		printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
@@ -191,11 +196,16 @@
 	}
 
 	if (is_multicast_ether_addr(eth->h_dest)) {
+		int count = 0;
 		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
 				i++)
-			if (rionet_active[i])
+			if (rionet_active[i]) {
 				rionet_queue_tx_msg(skb, ndev,
 						    rionet_active[i]);
+				if (count)
+					atomic_inc(&skb->users);
+				count++;
+			}
 	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
 		destid = RIONET_GET_DESTID(eth->h_dest);
 		if (rionet_active[destid])
@@ -220,14 +230,17 @@
 	if (info == RIONET_DOORBELL_JOIN) {
 		if (!rionet_active[sid]) {
 			list_for_each_entry(peer, &rionet_peers, node) {
-				if (peer->rdev->destid == sid)
+				if (peer->rdev->destid == sid) {
 					rionet_active[sid] = peer->rdev;
+					nact++;
+				}
 			}
 			rio_mport_send_doorbell(mport, sid,
 						RIONET_DOORBELL_JOIN);
 		}
 	} else if (info == RIONET_DOORBELL_LEAVE) {
 		rionet_active[sid] = NULL;
+		nact--;
 	} else {
 		if (netif_msg_intr(rnet))
 			printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -523,6 +536,7 @@
 
 		rc = rionet_setup_netdev(rdev->net->hport, ndev);
 		rionet_check = 1;
+		nact = 0;
 	}
 
 	/*
diff -druN linux-libre-3.6-gnu/drivers/net/usb/asix_devices.c linux-libre-3.6.3-gnu/drivers/net/usb/asix_devices.c
--- linux-libre-3.6-gnu/drivers/net/usb/asix_devices.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/usb/asix_devices.c	2012-10-21 12:32:56.000000000 -0400
@@ -930,6 +930,10 @@
 	USB_DEVICE (0x04f1, 0x3008),
 	.driver_info = (unsigned long) &ax8817x_info,
 }, {
+	// Lenovo U2L100P 10/100
+	USB_DEVICE (0x17ef, 0x7203),
+	.driver_info = (unsigned long) &ax88772_info,
+}, {
 	// ASIX AX88772B 10/100
 	USB_DEVICE (0x0b95, 0x772b),
 	.driver_info = (unsigned long) &ax88772_info,
diff -druN linux-libre-3.6-gnu/drivers/net/usb/mcs7830.c linux-libre-3.6.3-gnu/drivers/net/usb/mcs7830.c
--- linux-libre-3.6-gnu/drivers/net/usb/mcs7830.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/usb/mcs7830.c	2012-10-21 12:32:56.000000000 -0400
@@ -117,6 +117,7 @@
 struct mcs7830_data {
 	u8 multi_filter[8];
 	u8 config;
+	u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -632,20 +633,31 @@
 static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
 	u8 *buf = urb->transfer_buffer;
-	bool link;
+	bool link, link_changed;
+	struct mcs7830_data *data = mcs7830_get_data(dev);
 
 	if (urb->actual_length < 16)
 		return;
 
 	link = !(buf[1] & 0x20);
-	if (netif_carrier_ok(dev->net) != link) {
-		if (link) {
-			netif_carrier_on(dev->net);
-			usbnet_defer_kevent(dev, EVENT_LINK_RESET);
-		} else
-			netif_carrier_off(dev->net);
-		netdev_dbg(dev->net, "Link Status is: %d\n", link);
-	}
+	link_changed = netif_carrier_ok(dev->net) != link;
+	if (link_changed) {
+		data->link_counter++;
+		/*
+		   track link state 20 times to guard against erroneous
+		   link state changes reported sometimes by the chip
+		 */
+		if (data->link_counter > 20) {
+			data->link_counter = 0;
+			if (link) {
+				netif_carrier_on(dev->net);
+				usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+			} else
+				netif_carrier_off(dev->net);
+			netdev_dbg(dev->net, "Link Status is: %d\n", link);
+		}
+	} else
+		data->link_counter = 0;
 }
 
 static const struct driver_info moschip_info = {
diff -druN linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/beacon.c linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/beacon.c
--- linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2012-10-21 12:32:56.000000000 -0400
@@ -120,7 +120,7 @@
 
 	if (ath_tx_start(hw, skb, &txctl) != 0) {
 		ath_dbg(common, XMIT, "CABQ TX failed\n");
-		dev_kfree_skb_any(skb);
+		ieee80211_free_txskb(hw, skb);
 	}
 }
 
diff -druN linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/main.c linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/main.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/main.c	2012-10-21 12:32:56.000000000 -0400
@@ -767,7 +767,7 @@
 
 	return;
 exit:
-	dev_kfree_skb_any(skb);
+	ieee80211_free_txskb(hw, skb);
 }
 
 static void ath9k_stop(struct ieee80211_hw *hw)
diff -druN linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/pci.c linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/pci.c
--- linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/pci.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/pci.c	2012-10-21 12:32:56.000000000 -0400
@@ -127,8 +127,9 @@
 	if (!parent)
 		return;
 
-	if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
-		/* Bluetooth coexistance requires disabling ASPM. */
+	if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
+	    (AR_SREV_9285(ah))) {
+		/* Bluetooth coexistance requires disabling ASPM for AR9285. */
 		pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
 		aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
 		pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
diff -druN linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/xmit.c linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/xmit.c
--- linux-libre-3.6-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2012-10-21 12:32:56.000000000 -0400
@@ -66,8 +66,7 @@
 static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
 					   struct ath_txq *txq,
 					   struct ath_atx_tid *tid,
-					   struct sk_buff *skb,
-					   bool dequeue);
+					   struct sk_buff *skb);
 
 enum {
 	MCS_HT20,
@@ -176,7 +175,15 @@
 		fi = get_frame_info(skb);
 		bf = fi->bf;
 
-		if (bf && fi->retries) {
+		if (!bf) {
+			bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+			if (!bf) {
+				ieee80211_free_txskb(sc->hw, skb);
+				continue;
+			}
+		}
+
+		if (fi->retries) {
 			list_add_tail(&bf->list, &bf_head);
 			ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
@@ -785,10 +792,13 @@
 		fi = get_frame_info(skb);
 		bf = fi->bf;
 		if (!fi->bf)
-			bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
+			bf = ath_tx_setup_buffer(sc, txq, tid, skb);
 
-		if (!bf)
+		if (!bf) {
+			__skb_unlink(skb, &tid->buf_q);
+			ieee80211_free_txskb(sc->hw, skb);
 			continue;
+		}
 
 		bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
 		seqno = bf->bf_state.seqno;
@@ -1731,9 +1741,11 @@
 		return;
 	}
 
-	bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
-	if (!bf)
+	bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+	if (!bf) {
+		ieee80211_free_txskb(sc->hw, skb);
 		return;
+	}
 
 	bf->bf_state.bf_type = BUF_AMPDU;
 	INIT_LIST_HEAD(&bf_head);
@@ -1757,11 +1769,6 @@
 	struct ath_buf *bf;
 
 	bf = fi->bf;
-	if (!bf)
-		bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
-
-	if (!bf)
-		return;
 
 	INIT_LIST_HEAD(&bf_head);
 	list_add_tail(&bf->list, &bf_head);
@@ -1834,8 +1841,7 @@
 static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
 					   struct ath_txq *txq,
 					   struct ath_atx_tid *tid,
-					   struct sk_buff *skb,
-					   bool dequeue)
+					   struct sk_buff *skb)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_frame_info *fi = get_frame_info(skb);
@@ -1847,7 +1853,7 @@
 	bf = ath_tx_get_buffer(sc);
 	if (!bf) {
 		ath_dbg(common, XMIT, "TX buffers are full\n");
-		goto error;
+		return NULL;
 	}
 
 	ATH_TXBUF_RESET(bf);
@@ -1876,18 +1882,12 @@
 		ath_err(ath9k_hw_common(sc->sc_ah),
 			"dma_mapping_error() on TX\n");
 		ath_tx_return_buffer(sc, bf);
-		goto error;
+		return NULL;
 	}
 
 	fi->bf = bf;
 
 	return bf;
-
-error:
-	if (dequeue)
-		__skb_unlink(skb, &tid->buf_q);
-	dev_kfree_skb_any(skb);
-	return NULL;
 }
 
 /* FIXME: tx power */
@@ -1916,9 +1916,14 @@
 		 */
 		ath_tx_send_ampdu(sc, tid, skb, txctl);
 	} else {
-		bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
-		if (!bf)
+		bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+		if (!bf) {
+			if (txctl->paprd)
+				dev_kfree_skb_any(skb);
+			else
+				ieee80211_free_txskb(sc->hw, skb);
 			return;
+		}
 
 		bf->bf_state.bfs_paprd = txctl->paprd;
 
diff -druN linux-libre-3.6-gnu/drivers/net/wireless/b43legacy/main.c linux-libre-3.6.3-gnu/drivers/net/wireless/b43legacy/main.c
--- linux-libre-3.6-gnu/drivers/net/wireless/b43legacy/main.c	2012-09-30 20:57:01.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/net/wireless/b43legacy/main.c	2012-10-21 14:00:12.000000000 -0400
@@ -3891,6 +3891,8 @@
 	cancel_work_sync(&wl->firmware_load);
 
 	B43legacy_WARN_ON(!wl);
+	if (!wldev->fw.ucode)
+		return;			/* NULL if fw never loaded */
 	if (wl->current_dev == wldev)
 		ieee80211_unregister_hw(wl->hw);
 
diff -druN linux-libre-3.6-gnu/drivers/pci/probe.c linux-libre-3.6.3-gnu/drivers/pci/probe.c
--- linux-libre-3.6-gnu/drivers/pci/probe.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/pci/probe.c	2012-10-21 12:32:56.000000000 -0400
@@ -729,8 +729,10 @@
 
 	/* Check if setup is sensible at all */
 	if (!pass &&
-	    (primary != bus->number || secondary <= bus->number)) {
-		dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
+	    (primary != bus->number || secondary <= bus->number ||
+	     secondary > subordinate)) {
+		dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
+			 secondary, subordinate);
 		broken = 1;
 	}
 
diff -druN linux-libre-3.6-gnu/drivers/remoteproc/Kconfig linux-libre-3.6.3-gnu/drivers/remoteproc/Kconfig
--- linux-libre-3.6-gnu/drivers/remoteproc/Kconfig	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/remoteproc/Kconfig	2012-10-21 12:32:56.000000000 -0400
@@ -5,6 +5,7 @@
 	tristate
 	depends on EXPERIMENTAL
 	select FW_CONFIG
+	select VIRTIO
 
 config OMAP_REMOTEPROC
 	tristate "OMAP remoteproc support"
diff -druN linux-libre-3.6-gnu/drivers/remoteproc/remoteproc_core.c linux-libre-3.6.3-gnu/drivers/remoteproc/remoteproc_core.c
--- linux-libre-3.6-gnu/drivers/remoteproc/remoteproc_core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/remoteproc/remoteproc_core.c	2012-10-21 12:32:56.000000000 -0400
@@ -545,17 +545,10 @@
 	dev_dbg(dev, "carveout rsc: da %x, pa %x, len %x, flags %x\n",
 			rsc->da, rsc->pa, rsc->len, rsc->flags);
 
-	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
-	if (!mapping) {
-		dev_err(dev, "kzalloc mapping failed\n");
-		return -ENOMEM;
-	}
-
 	carveout = kzalloc(sizeof(*carveout), GFP_KERNEL);
 	if (!carveout) {
 		dev_err(dev, "kzalloc carveout failed\n");
-		ret = -ENOMEM;
-		goto free_mapping;
+		return -ENOMEM;
 	}
 
 	va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL);
@@ -585,11 +578,18 @@
 	 * physical address in this case.
 	 */
 	if (rproc->domain) {
+		mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+		if (!mapping) {
+			dev_err(dev, "kzalloc mapping failed\n");
+			ret = -ENOMEM;
+			goto dma_free;
+		}
+
 		ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len,
 								rsc->flags);
 		if (ret) {
 			dev_err(dev, "iommu_map failed: %d\n", ret);
-			goto dma_free;
+			goto free_mapping;
 		}
 
 		/*
@@ -634,12 +634,12 @@
 
 	return 0;
 
+free_mapping:
+	kfree(mapping);
 dma_free:
 	dma_free_coherent(dev->parent, rsc->len, va, dma);
 free_carv:
 	kfree(carveout);
-free_mapping:
-	kfree(mapping);
 	return ret;
 }
 
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_aux.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_aux.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_aux.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_aux.c	2012-10-21 12:32:56.000000000 -0400
@@ -519,6 +519,7 @@
 
 	rwlock_init(&port->unit_list_lock);
 	INIT_LIST_HEAD(&port->unit_list);
+	atomic_set(&port->units, 0);
 
 	INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
 	INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_ccw.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_ccw.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_ccw.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_ccw.c	2012-10-21 12:32:56.000000000 -0400
@@ -39,17 +39,23 @@
 	spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
 }
 
-static int zfcp_ccw_activate(struct ccw_device *cdev)
-
+/**
+ * zfcp_ccw_activate - activate adapter and wait for it to finish
+ * @cdev: pointer to belonging ccw device
+ * @clear: Status flags to clear.
+ * @tag: s390dbf trace record tag
+ */
+static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
 {
 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 
 	if (!adapter)
 		return 0;
 
+	zfcp_erp_clear_adapter_status(adapter, clear);
 	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-				"ccresu2");
+				tag);
 	zfcp_erp_wait(adapter);
 	flush_work(&adapter->scan_work);
 
@@ -164,26 +170,29 @@
 	BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
 	adapter->req_no = 0;
 
-	zfcp_ccw_activate(cdev);
+	zfcp_ccw_activate(cdev, 0, "ccsonl1");
 	zfcp_ccw_adapter_put(adapter);
 	return 0;
 }
 
 /**
- * zfcp_ccw_set_offline - set_offline function of zfcp driver
+ * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
  * @cdev: pointer to belonging ccw device
+ * @set: Status flags to set.
+ * @tag: s390dbf trace record tag
  *
  * This function gets called by the common i/o layer and sets an adapter
  * into state offline.
  */
-static int zfcp_ccw_set_offline(struct ccw_device *cdev)
+static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
 {
 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
 
 	if (!adapter)
 		return 0;
 
-	zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");
+	zfcp_erp_set_adapter_status(adapter, set);
+	zfcp_erp_adapter_shutdown(adapter, 0, tag);
 	zfcp_erp_wait(adapter);
 
 	zfcp_ccw_adapter_put(adapter);
@@ -191,6 +200,18 @@
 }
 
 /**
+ * zfcp_ccw_set_offline - set_offline function of zfcp driver
+ * @cdev: pointer to belonging ccw device
+ *
+ * This function gets called by the common i/o layer and sets an adapter
+ * into state offline.
+ */
+static int zfcp_ccw_set_offline(struct ccw_device *cdev)
+{
+	return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
+}
+
+/**
  * zfcp_ccw_notify - ccw notify function
  * @cdev: pointer to belonging ccw device
  * @event: indicates if adapter was detached or attached
@@ -207,6 +228,11 @@
 
 	switch (event) {
 	case CIO_GONE:
+		if (atomic_read(&adapter->status) &
+		    ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
+			zfcp_dbf_hba_basic("ccnigo1", adapter);
+			break;
+		}
 		dev_warn(&cdev->dev, "The FCP device has been detached\n");
 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
 		break;
@@ -216,6 +242,11 @@
 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
 		break;
 	case CIO_OPER:
+		if (atomic_read(&adapter->status) &
+		    ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
+			zfcp_dbf_hba_basic("ccniop1", adapter);
+			break;
+		}
 		dev_info(&cdev->dev, "The FCP device is operational again\n");
 		zfcp_erp_set_adapter_status(adapter,
 					    ZFCP_STATUS_COMMON_RUNNING);
@@ -251,6 +282,28 @@
 	zfcp_ccw_adapter_put(adapter);
 }
 
+static int zfcp_ccw_suspend(struct ccw_device *cdev)
+{
+	zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
+	return 0;
+}
+
+static int zfcp_ccw_thaw(struct ccw_device *cdev)
+{
+	/* trace records for thaw and final shutdown during suspend
+	   can only be found in system dump until the end of suspend
+	   but not after resume because it's based on the memory image
+	   right after the very first suspend (freeze) callback */
+	zfcp_ccw_activate(cdev, 0, "ccthaw1");
+	return 0;
+}
+
+static int zfcp_ccw_resume(struct ccw_device *cdev)
+{
+	zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
+	return 0;
+}
+
 struct ccw_driver zfcp_ccw_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
@@ -263,7 +316,7 @@
 	.set_offline = zfcp_ccw_set_offline,
 	.notify      = zfcp_ccw_notify,
 	.shutdown    = zfcp_ccw_shutdown,
-	.freeze      = zfcp_ccw_set_offline,
-	.thaw	     = zfcp_ccw_activate,
-	.restore     = zfcp_ccw_activate,
+	.freeze      = zfcp_ccw_suspend,
+	.thaw	     = zfcp_ccw_thaw,
+	.restore     = zfcp_ccw_resume,
 };
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_cfdc.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_cfdc.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_cfdc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_cfdc.c	2012-10-21 12:32:56.000000000 -0400
@@ -293,7 +293,7 @@
 	}
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-	shost_for_each_device(sdev, port->adapter->scsi_host) {
+	shost_for_each_device(sdev, adapter->scsi_host) {
 		zfcp_sdev = sdev_to_zfcp(sdev);
 		status = atomic_read(&zfcp_sdev->status);
 		if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_dbf.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_dbf.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_dbf.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_dbf.c	2012-10-21 12:32:56.000000000 -0400
@@ -191,7 +191,7 @@
 	length = min((u16)sizeof(struct qdio_buffer),
 		     (u16)ZFCP_DBF_PAY_MAX_REC);
 
-	while ((char *)pl[payload->counter] && payload->counter < scount) {
+	while (payload->counter < scount && (char *)pl[payload->counter]) {
 		memcpy(payload->data, (char *)pl[payload->counter], length);
 		debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
 		payload->counter++;
@@ -200,6 +200,26 @@
 	spin_unlock_irqrestore(&dbf->pay_lock, flags);
 }
 
+/**
+ * zfcp_dbf_hba_basic - trace event for basic adapter events
+ * @adapter: pointer to struct zfcp_adapter
+ */
+void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter)
+{
+	struct zfcp_dbf *dbf = adapter->dbf;
+	struct zfcp_dbf_hba *rec = &dbf->hba_buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dbf->hba_lock, flags);
+	memset(rec, 0, sizeof(*rec));
+
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->id = ZFCP_DBF_HBA_BASIC;
+
+	debug_event(dbf->hba, 1, rec, sizeof(*rec));
+	spin_unlock_irqrestore(&dbf->hba_lock, flags);
+}
+
 static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
 				struct zfcp_adapter *adapter,
 				struct zfcp_port *port,
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_dbf.h linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_dbf.h
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_dbf.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_dbf.h	2012-10-21 12:32:56.000000000 -0400
@@ -154,6 +154,7 @@
 	ZFCP_DBF_HBA_RES	= 1,
 	ZFCP_DBF_HBA_USS	= 2,
 	ZFCP_DBF_HBA_BIT	= 3,
+	ZFCP_DBF_HBA_BASIC	= 4,
 };
 
 /**
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_def.h linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_def.h
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_def.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_def.h	2012-10-21 12:32:56.000000000 -0400
@@ -77,6 +77,7 @@
 #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED	0x00000004
 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK		0x00000008
 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT	0x00000010
+#define ZFCP_STATUS_ADAPTER_SUSPENDED		0x00000040
 #define ZFCP_STATUS_ADAPTER_ERP_PENDING		0x00000100
 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED	0x00000200
 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED	0x00000400
@@ -204,6 +205,7 @@
 	struct zfcp_adapter    *adapter;       /* adapter used to access port */
 	struct list_head	unit_list;	/* head of logical unit list */
 	rwlock_t		unit_list_lock; /* unit list lock */
+	atomic_t		units;	       /* zfcp_unit count */
 	atomic_t	       status;	       /* status of this remote port */
 	u64		       wwnn;	       /* WWNN if known */
 	u64		       wwpn;	       /* WWPN */
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_ext.h linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_ext.h
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_ext.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_ext.h	2012-10-21 12:32:56.000000000 -0400
@@ -54,6 +54,7 @@
 extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
+extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
 extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
 extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
@@ -158,6 +159,7 @@
 extern struct attribute_group zfcp_sysfs_unit_attrs;
 extern struct attribute_group zfcp_sysfs_adapter_attrs;
 extern struct attribute_group zfcp_sysfs_port_attrs;
+extern struct mutex zfcp_sysfs_port_units_mutex;
 extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
 extern struct device_attribute *zfcp_sysfs_shost_attrs[];
 
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_fsf.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_fsf.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_fsf.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_fsf.c	2012-10-21 12:32:56.000000000 -0400
@@ -219,7 +219,7 @@
 		return;
 	}
 
-	zfcp_dbf_hba_fsf_uss("fssrh_2", req);
+	zfcp_dbf_hba_fsf_uss("fssrh_4", req);
 
 	switch (sr_buf->status_type) {
 	case FSF_STATUS_READ_PORT_CLOSED:
@@ -437,6 +437,34 @@
 	}
 }
 
+#define ZFCP_FSF_PORTSPEED_1GBIT	(1 <<  0)
+#define ZFCP_FSF_PORTSPEED_2GBIT	(1 <<  1)
+#define ZFCP_FSF_PORTSPEED_4GBIT	(1 <<  2)
+#define ZFCP_FSF_PORTSPEED_10GBIT	(1 <<  3)
+#define ZFCP_FSF_PORTSPEED_8GBIT	(1 <<  4)
+#define ZFCP_FSF_PORTSPEED_16GBIT	(1 <<  5)
+#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15)
+
+static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
+{
+	u32 fdmi_speed = 0;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT)
+		fdmi_speed |= FC_PORTSPEED_1GBIT;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT)
+		fdmi_speed |= FC_PORTSPEED_2GBIT;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT)
+		fdmi_speed |= FC_PORTSPEED_4GBIT;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT)
+		fdmi_speed |= FC_PORTSPEED_10GBIT;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT)
+		fdmi_speed |= FC_PORTSPEED_8GBIT;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT)
+		fdmi_speed |= FC_PORTSPEED_16GBIT;
+	if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED)
+		fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED;
+	return fdmi_speed;
+}
+
 static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
 {
 	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
@@ -456,7 +484,8 @@
 	fc_host_port_name(shost) = nsp->fl_wwpn;
 	fc_host_node_name(shost) = nsp->fl_wwnn;
 	fc_host_port_id(shost) = ntoh24(bottom->s_id);
-	fc_host_speed(shost) = bottom->fc_link_speed;
+	fc_host_speed(shost) =
+		zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
 	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
 
 	adapter->hydra_version = bottom->adapter_type;
@@ -580,7 +609,8 @@
 	} else
 		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
 	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
-	fc_host_supported_speeds(shost) = bottom->supported_speed;
+	fc_host_supported_speeds(shost) =
+		zfcp_fsf_convert_portspeed(bottom->supported_speed);
 	memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
 	       FC_FC4_LIST_SIZE);
 	memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
@@ -771,12 +801,14 @@
 static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 {
 	struct scsi_device *sdev = req->data;
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_scsi_dev *zfcp_sdev;
 	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
+	zfcp_sdev = sdev_to_zfcp(sdev);
+
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
@@ -885,7 +917,7 @@
 
 	switch (header->fsf_status) {
         case FSF_GOOD:
-		zfcp_dbf_san_res("fsscth1", req);
+		zfcp_dbf_san_res("fsscth2", req);
 		ct->status = 0;
 		break;
         case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1739,13 +1771,15 @@
 {
 	struct zfcp_adapter *adapter = req->adapter;
 	struct scsi_device *sdev = req->data;
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_scsi_dev *zfcp_sdev;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
+	zfcp_sdev = sdev_to_zfcp(sdev);
+
 	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
 			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
 			  ZFCP_STATUS_LUN_SHARED |
@@ -1856,11 +1890,13 @@
 static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
 {
 	struct scsi_device *sdev = req->data;
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
+	zfcp_sdev = sdev_to_zfcp(sdev);
+
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
 		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
@@ -1950,7 +1986,7 @@
 {
 	struct fsf_qual_latency_info *lat_in;
 	struct latency_cont *lat = NULL;
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
+	struct zfcp_scsi_dev *zfcp_sdev;
 	struct zfcp_blk_drv_data blktrc;
 	int ticks = req->adapter->timer_ticks;
 
@@ -1965,6 +2001,7 @@
 
 	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
 	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
+		zfcp_sdev = sdev_to_zfcp(scsi->device);
 		blktrc.flags |= ZFCP_BLK_LAT_VALID;
 		blktrc.channel_lat = lat_in->channel_lat * ticks;
 		blktrc.fabric_lat = lat_in->fabric_lat * ticks;
@@ -2002,12 +2039,14 @@
 {
 	struct scsi_cmnd *scmnd = req->data;
 	struct scsi_device *sdev = scmnd->device;
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_scsi_dev *zfcp_sdev;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 
 	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
 		return;
 
+	zfcp_sdev = sdev_to_zfcp(sdev);
+
 	switch (header->fsf_status) {
 	case FSF_HANDLE_MISMATCH:
 	case FSF_PORT_HANDLE_NOT_VALID:
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_qdio.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_qdio.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_qdio.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_qdio.c	2012-10-21 12:32:56.000000000 -0400
@@ -102,18 +102,22 @@
 {
 	struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
 	struct zfcp_adapter *adapter = qdio->adapter;
-	struct qdio_buffer_element *sbale;
 	int sbal_no, sbal_idx;
-	void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
-	u64 req_id;
-	u8 scount;
 
 	if (unlikely(qdio_err)) {
-		memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
 		if (zfcp_adapter_multi_buffer_active(adapter)) {
+			void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
+			struct qdio_buffer_element *sbale;
+			u64 req_id;
+			u8 scount;
+
+			memset(pl, 0,
+			       ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
 			sbale = qdio->res_q[idx]->element;
 			req_id = (u64) sbale->addr;
-			scount = sbale->scount + 1; /* incl. signaling SBAL */
+			scount = min(sbale->scount + 1,
+				     ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
+				     /* incl. signaling SBAL */
 
 			for (sbal_no = 0; sbal_no < scount; sbal_no++) {
 				sbal_idx = (idx + sbal_no) %
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_sysfs.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_sysfs.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_sysfs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_sysfs.c	2012-10-21 12:32:56.000000000 -0400
@@ -227,6 +227,8 @@
 static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
 		     zfcp_sysfs_port_rescan_store);
 
+DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
+
 static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
 					    struct device_attribute *attr,
 					    const char *buf, size_t count)
@@ -249,6 +251,16 @@
 	else
 		retval = 0;
 
+	mutex_lock(&zfcp_sysfs_port_units_mutex);
+	if (atomic_read(&port->units) > 0) {
+		retval = -EBUSY;
+		mutex_unlock(&zfcp_sysfs_port_units_mutex);
+		goto out;
+	}
+	/* port is about to be removed, so no more unit_add */
+	atomic_set(&port->units, -1);
+	mutex_unlock(&zfcp_sysfs_port_units_mutex);
+
 	write_lock_irq(&adapter->port_list_lock);
 	list_del(&port->list);
 	write_unlock_irq(&adapter->port_list_lock);
@@ -289,12 +301,14 @@
 {
 	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
 	u64 fcp_lun;
+	int retval;
 
 	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
 		return -EINVAL;
 
-	if (zfcp_unit_add(port, fcp_lun))
-		return -EINVAL;
+	retval = zfcp_unit_add(port, fcp_lun);
+	if (retval)
+		return retval;
 
 	return count;
 }
diff -druN linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_unit.c linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_unit.c
--- linux-libre-3.6-gnu/drivers/s390/scsi/zfcp_unit.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/s390/scsi/zfcp_unit.c	2012-10-21 12:32:56.000000000 -0400
@@ -104,7 +104,7 @@
 {
 	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
 
-	put_device(&unit->port->dev);
+	atomic_dec(&unit->port->units);
 	kfree(unit);
 }
 
@@ -119,16 +119,27 @@
 int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
 {
 	struct zfcp_unit *unit;
+	int retval = 0;
+
+	mutex_lock(&zfcp_sysfs_port_units_mutex);
+	if (atomic_read(&port->units) == -1) {
+		/* port is already gone */
+		retval = -ENODEV;
+		goto out;
+	}
 
 	unit = zfcp_unit_find(port, fcp_lun);
 	if (unit) {
 		put_device(&unit->dev);
-		return -EEXIST;
+		retval = -EEXIST;
+		goto out;
 	}
 
 	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
-	if (!unit)
-		return -ENOMEM;
+	if (!unit) {
+		retval = -ENOMEM;
+		goto out;
+	}
 
 	unit->port = port;
 	unit->fcp_lun = fcp_lun;
@@ -139,28 +150,33 @@
 	if (dev_set_name(&unit->dev, "0x%016llx",
 			 (unsigned long long) fcp_lun)) {
 		kfree(unit);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto out;
 	}
 
-	get_device(&port->dev);
-
 	if (device_register(&unit->dev)) {
 		put_device(&unit->dev);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto out;
 	}
 
 	if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
 		device_unregister(&unit->dev);
-		return -EINVAL;
+		retval = -EINVAL;
+		goto out;
 	}
 
+	atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
+
 	write_lock_irq(&port->unit_list_lock);
 	list_add_tail(&unit->list, &port->unit_list);
 	write_unlock_irq(&port->unit_list_lock);
 
 	zfcp_unit_scsi_scan(unit);
 
-	return 0;
+out:
+	mutex_unlock(&zfcp_sysfs_port_units_mutex);
+	return retval;
 }
 
 /**
diff -druN linux-libre-3.6-gnu/drivers/scsi/atp870u.c linux-libre-3.6.3-gnu/drivers/scsi/atp870u.c
--- linux-libre-3.6-gnu/drivers/scsi/atp870u.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/atp870u.c	2012-10-21 12:32:56.000000000 -0400
@@ -1173,7 +1173,16 @@
 	outw(val, tmport);
 	outb(2, 0x80);
 TCM_SYNC:
-	udelay(0x800);
+	/*
+	 * The funny division into multiple delays is to accomodate
+	 * arches like ARM where udelay() multiplies its argument by
+	 * a large number to initialize a loop counter.  To avoid
+	 * overflow, the maximum supported udelay is 2000 microseconds.
+	 *
+	 * XXX it would be more polite to find a way to use msleep()
+	 */
+	mdelay(2);
+	udelay(48);
 	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
 		outw(0, tmport--);
 		outb(0, tmport);
diff -druN linux-libre-3.6-gnu/drivers/scsi/device_handler/scsi_dh_alua.c linux-libre-3.6.3-gnu/drivers/scsi/device_handler/scsi_dh_alua.c
--- linux-libre-3.6-gnu/drivers/scsi/device_handler/scsi_dh_alua.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/device_handler/scsi_dh_alua.c	2012-10-21 12:32:56.000000000 -0400
@@ -641,8 +641,7 @@
 		h->state = TPGS_STATE_STANDBY;
 		break;
 	case TPGS_STATE_OFFLINE:
-	case TPGS_STATE_UNAVAILABLE:
-		/* Path unusable for unavailable/offline */
+		/* Path unusable */
 		err = SCSI_DH_DEV_OFFLINED;
 		break;
 	default:
diff -druN linux-libre-3.6-gnu/drivers/scsi/hpsa.c linux-libre-3.6.3-gnu/drivers/scsi/hpsa.c
--- linux-libre-3.6-gnu/drivers/scsi/hpsa.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/hpsa.c	2012-10-21 12:32:56.000000000 -0400
@@ -3266,7 +3266,7 @@
 			c->Request.Timeout = 0; /* Don't time out */
 			memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
 			c->Request.CDB[0] =  cmd;
-			c->Request.CDB[1] = 0x03;  /* Reset target above */
+			c->Request.CDB[1] = HPSA_RESET_TYPE_LUN;
 			/* If bytes 4-7 are zero, it means reset the */
 			/* LunID device */
 			c->Request.CDB[4] = 0x00;
diff -druN linux-libre-3.6-gnu/drivers/scsi/ibmvscsi/ibmvscsi.c linux-libre-3.6.3-gnu/drivers/scsi/ibmvscsi/ibmvscsi.c
--- linux-libre-3.6-gnu/drivers/scsi/ibmvscsi/ibmvscsi.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/ibmvscsi/ibmvscsi.c	2012-10-21 12:32:56.000000000 -0400
@@ -1541,6 +1541,9 @@
 
 	host_config = &evt_struct->iu.mad.host_config;
 
+	/* The transport length field is only 16-bit */
+	length = min(0xffff, length);
+
 	/* Set up a lun reset SRP command */
 	memset(host_config, 0x00, sizeof(*host_config));
 	host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
diff -druN linux-libre-3.6-gnu/drivers/scsi/isci/init.c linux-libre-3.6.3-gnu/drivers/scsi/isci/init.c
--- linux-libre-3.6-gnu/drivers/scsi/isci/init.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/isci/init.c	2012-10-21 12:32:56.000000000 -0400
@@ -644,7 +644,6 @@
 						orom->hdr.version)) {
 			dev_warn(&pdev->dev,
 				 "[%d]: invalid oem parameters detected, falling back to firmware\n", i);
-			devm_kfree(&pdev->dev, orom);
 			orom = NULL;
 			break;
 		}
diff -druN linux-libre-3.6-gnu/drivers/scsi/isci/probe_roms.c linux-libre-3.6.3-gnu/drivers/scsi/isci/probe_roms.c
--- linux-libre-3.6-gnu/drivers/scsi/isci/probe_roms.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/isci/probe_roms.c	2012-10-21 12:32:56.000000000 -0400
@@ -104,7 +104,6 @@
 
 	if (i >= len) {
 		dev_err(&pdev->dev, "oprom parse error\n");
-		devm_kfree(&pdev->dev, rom);
 		rom = NULL;
 	}
 	pci_unmap_biosrom(oprom);
diff -druN linux-libre-3.6-gnu/drivers/scsi/qla2xxx/qla_target.c linux-libre-3.6.3-gnu/drivers/scsi/qla2xxx/qla_target.c
--- linux-libre-3.6-gnu/drivers/scsi/qla2xxx/qla_target.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/qla2xxx/qla_target.c	2012-10-21 12:32:56.000000000 -0400
@@ -1403,7 +1403,7 @@
 	ctio->u.status1.scsi_status =
 	    __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID);
 	ctio->u.status1.response_len = __constant_cpu_to_le16(8);
-	((uint32_t *)ctio->u.status1.sense_data)[0] = cpu_to_be32(resp_code);
+	ctio->u.status1.sense_data[0] = resp_code;
 
 	qla2x00_start_iocbs(ha, ha->req);
 }
diff -druN linux-libre-3.6-gnu/drivers/scsi/scsi_debug.c linux-libre-3.6.3-gnu/drivers/scsi/scsi_debug.c
--- linux-libre-3.6-gnu/drivers/scsi/scsi_debug.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/scsi_debug.c	2012-10-21 12:32:56.000000000 -0400
@@ -2054,7 +2054,7 @@
 		block = lba + alignment;
 		rem = do_div(block, granularity);
 
-		if (rem == 0 && lba + granularity <= end && block < map_size) {
+		if (rem == 0 && lba + granularity < end && block < map_size) {
 			clear_bit(block, map_storep);
 			if (scsi_debug_lbprz)
 				memset(fake_storep +
diff -druN linux-libre-3.6-gnu/drivers/scsi/scsi_sysfs.c linux-libre-3.6.3-gnu/drivers/scsi/scsi_sysfs.c
--- linux-libre-3.6-gnu/drivers/scsi/scsi_sysfs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/scsi_sysfs.c	2012-10-21 12:32:56.000000000 -0400
@@ -1031,33 +1031,31 @@
 void scsi_remove_target(struct device *dev)
 {
 	struct Scsi_Host *shost = dev_to_shost(dev->parent);
-	struct scsi_target *starget, *found;
+	struct scsi_target *starget, *last = NULL;
 	unsigned long flags;
 
- restart:
-	found = NULL;
+	/* remove targets being careful to lookup next entry before
+	 * deleting the last
+	 */
 	spin_lock_irqsave(shost->host_lock, flags);
 	list_for_each_entry(starget, &shost->__targets, siblings) {
 		if (starget->state == STARGET_DEL)
 			continue;
 		if (starget->dev.parent == dev || &starget->dev == dev) {
-			found = starget;
-			found->reap_ref++;
-			break;
+			/* assuming new targets arrive at the end */
+			starget->reap_ref++;
+			spin_unlock_irqrestore(shost->host_lock, flags);
+			if (last)
+				scsi_target_reap(last);
+			last = starget;
+			__scsi_remove_target(starget);
+			spin_lock_irqsave(shost->host_lock, flags);
 		}
 	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
-	if (found) {
-		__scsi_remove_target(found);
-		scsi_target_reap(found);
-		/* in the case where @dev has multiple starget children,
-		 * continue removing.
-		 *
-		 * FIXME: does such a case exist?
-		 */
-		goto restart;
-	}
+	if (last)
+		scsi_target_reap(last);
 }
 EXPORT_SYMBOL(scsi_remove_target);
 
diff -druN linux-libre-3.6-gnu/drivers/scsi/storvsc_drv.c linux-libre-3.6.3-gnu/drivers/scsi/storvsc_drv.c
--- linux-libre-3.6-gnu/drivers/scsi/storvsc_drv.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/storvsc_drv.c	2012-10-21 12:32:56.000000000 -0400
@@ -1221,7 +1221,12 @@
 	/*
 	 * At this point, all outstanding requests in the adapter
 	 * should have been flushed out and return to us
+	 * There is a potential race here where the host may be in
+	 * the process of responding when we return from here.
+	 * Just wait for all in-transit packets to be accounted for
+	 * before we return from here.
 	 */
+	storvsc_wait_to_drain(stor_device);
 
 	return SUCCESS;
 }
diff -druN linux-libre-3.6-gnu/drivers/scsi/virtio_scsi.c linux-libre-3.6.3-gnu/drivers/scsi/virtio_scsi.c
--- linux-libre-3.6-gnu/drivers/scsi/virtio_scsi.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/scsi/virtio_scsi.c	2012-10-21 12:32:56.000000000 -0400
@@ -219,7 +219,7 @@
 	struct scatterlist sg;
 	unsigned long flags;
 
-	sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
+	sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
 
 	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
 
diff -druN linux-libre-3.6-gnu/drivers/staging/comedi/comedi_fops.c linux-libre-3.6.3-gnu/drivers/staging/comedi/comedi_fops.c
--- linux-libre-3.6-gnu/drivers/staging/comedi/comedi_fops.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/staging/comedi/comedi_fops.c	2012-10-21 12:32:56.000000000 -0400
@@ -951,7 +951,7 @@
 				ret = -EAGAIN;
 				break;
 			}
-			ret = s->async->inttrig(dev, s, insn->data[0]);
+			ret = s->async->inttrig(dev, s, data[0]);
 			if (ret >= 0)
 				ret = 1;
 			break;
@@ -1196,7 +1196,6 @@
 		goto cleanup;
 	}
 
-	kfree(async->cmd.chanlist);
 	async->cmd = user_cmd;
 	async->cmd.data = NULL;
 	/* load channel/gain list */
@@ -2033,6 +2032,8 @@
 	if (async) {
 		comedi_reset_async_buf(async);
 		async->inttrig = NULL;
+		kfree(async->cmd.chanlist);
+		async->cmd.chanlist = NULL;
 	} else {
 		printk(KERN_ERR
 		       "BUG: (?) do_become_nonbusy called with async=0\n");
diff -druN linux-libre-3.6-gnu/drivers/staging/comedi/drivers/jr3_pci.c linux-libre-3.6.3-gnu/drivers/staging/comedi/drivers/jr3_pci.c
--- linux-libre-3.6-gnu/drivers/staging/comedi/drivers/jr3_pci.c	2012-09-30 21:01:10.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/staging/comedi/drivers/jr3_pci.c	2012-10-21 14:06:35.000000000 -0400
@@ -884,7 +884,7 @@
 	}
 
 	/*  Reset DSP card */
-	devpriv->iobase->channel[0].reset = 0;
+	writel(0, &devpriv->iobase->channel[0].reset);
 
 	result = comedi_load_firmware(dev, "/*(DEBLOBBED)*/", jr3_download_firmware);
 	dev_dbg(dev->class_dev, "Firmare load %d\n", result);
diff -druN linux-libre-3.6-gnu/drivers/staging/comedi/drivers/s626.c linux-libre-3.6.3-gnu/drivers/staging/comedi/drivers/s626.c
--- linux-libre-3.6-gnu/drivers/staging/comedi/drivers/s626.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/staging/comedi/drivers/s626.c	2012-10-21 12:32:56.000000000 -0400
@@ -1868,7 +1868,7 @@
 	/*   (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
 
 	k->SetMode(dev, k, Setup, TRUE);
-	Preload(dev, k, *(insn->data));
+	Preload(dev, k, data[0]);
 	k->PulseIndex(dev, k);
 	SetLatchSource(dev, k, valueSrclatch);
 	k->SetEnable(dev, k, (uint16_t) (enab != 0));
diff -druN linux-libre-3.6-gnu/drivers/staging/rtl8712/rtl8712_recv.c linux-libre-3.6.3-gnu/drivers/staging/rtl8712/rtl8712_recv.c
--- linux-libre-3.6-gnu/drivers/staging/rtl8712/rtl8712_recv.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/staging/rtl8712/rtl8712_recv.c	2012-10-21 12:32:56.000000000 -0400
@@ -1127,6 +1127,9 @@
 		recvbuf2recvframe(padapter, pskb);
 		skb_reset_tail_pointer(pskb);
 		pskb->len = 0;
-		skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+		if (!skb_cloned(pskb))
+			skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+		else
+			consume_skb(pskb);
 	}
 }
diff -druN linux-libre-3.6-gnu/drivers/staging/speakup/speakup_soft.c linux-libre-3.6.3-gnu/drivers/staging/speakup/speakup_soft.c
--- linux-libre-3.6-gnu/drivers/staging/speakup/speakup_soft.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/staging/speakup/speakup_soft.c	2012-10-21 12:32:56.000000000 -0400
@@ -40,7 +40,7 @@
 static unsigned char get_index(void);
 
 static struct miscdevice synth_device;
-static int initialized;
+static int init_pos;
 static int misc_registered;
 
 static struct var_t vars[] = {
@@ -194,7 +194,7 @@
 	unsigned long flags;
 	spk_lock(flags);
 	synth_soft.alive = 0;
-	initialized = 0;
+	init_pos = 0;
 	spk_unlock(flags);
 	/* Make sure we let applications go before leaving */
 	speakup_start_ttys();
@@ -239,13 +239,8 @@
 			ch = '\x18';
 		} else if (synth_buffer_empty()) {
 			break;
-		} else if (!initialized) {
-			if (*init) {
-				ch = *init;
-				init++;
-			} else {
-				initialized = 1;
-			}
+		} else if (init[init_pos]) {
+			ch = init[init_pos++];
 		} else {
 			ch = synth_buffer_getc();
 		}
diff -druN linux-libre-3.6-gnu/drivers/target/iscsi/iscsi_target.c linux-libre-3.6.3-gnu/drivers/target/iscsi/iscsi_target.c
--- linux-libre-3.6-gnu/drivers/target/iscsi/iscsi_target.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/iscsi/iscsi_target.c	2012-10-21 12:32:56.000000000 -0400
@@ -3271,7 +3271,6 @@
 		len += 1;
 
 		if ((len + payload_len) > buffer_len) {
-			spin_unlock(&tiqn->tiqn_tpg_lock);
 			end_of_buf = 1;
 			goto eob;
 		}
@@ -3424,6 +3423,7 @@
 	hdr->opcode		= ISCSI_OP_REJECT;
 	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
 	hton24(hdr->dlength, ISCSI_HDR_LEN);
+	hdr->ffffffff		= 0xffffffff;
 	cmd->stat_sn		= conn->stat_sn++;
 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
 	hdr->exp_cmdsn	= cpu_to_be32(conn->sess->exp_cmd_sn);
diff -druN linux-libre-3.6-gnu/drivers/target/iscsi/iscsi_target_core.h linux-libre-3.6.3-gnu/drivers/target/iscsi/iscsi_target_core.h
--- linux-libre-3.6-gnu/drivers/target/iscsi/iscsi_target_core.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/iscsi/iscsi_target_core.h	2012-10-21 12:32:56.000000000 -0400
@@ -25,10 +25,10 @@
 #define NA_DATAOUT_TIMEOUT_RETRIES	5
 #define NA_DATAOUT_TIMEOUT_RETRIES_MAX	15
 #define NA_DATAOUT_TIMEOUT_RETRIES_MIN	1
-#define NA_NOPIN_TIMEOUT		5
+#define NA_NOPIN_TIMEOUT		15
 #define NA_NOPIN_TIMEOUT_MAX		60
 #define NA_NOPIN_TIMEOUT_MIN		3
-#define NA_NOPIN_RESPONSE_TIMEOUT	5
+#define NA_NOPIN_RESPONSE_TIMEOUT	30
 #define NA_NOPIN_RESPONSE_TIMEOUT_MAX	60
 #define NA_NOPIN_RESPONSE_TIMEOUT_MIN	3
 #define NA_RANDOM_DATAIN_PDU_OFFSETS	0
diff -druN linux-libre-3.6-gnu/drivers/target/iscsi/iscsi_target_tpg.c linux-libre-3.6.3-gnu/drivers/target/iscsi/iscsi_target_tpg.c
--- linux-libre-3.6-gnu/drivers/target/iscsi/iscsi_target_tpg.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/iscsi/iscsi_target_tpg.c	2012-10-21 12:32:56.000000000 -0400
@@ -677,6 +677,12 @@
 	pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n",
 		tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled");
 
+	if (flag == 1 && a->cache_dynamic_acls == 0) {
+		pr_debug("Explicitly setting cache_dynamic_acls=1 when "
+			"generate_node_acls=1\n");
+		a->cache_dynamic_acls = 1;
+	}
+
 	return 0;
 }
 
@@ -716,6 +722,12 @@
 		return -EINVAL;
 	}
 
+	if (a->generate_node_acls == 1 && flag == 0) {
+		pr_debug("Skipping cache_dynamic_acls=0 when"
+			" generate_node_acls=1\n");
+		return 0;
+	}
+
 	a->cache_dynamic_acls = flag;
 	pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group"
 		" ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ?
diff -druN linux-libre-3.6-gnu/drivers/target/target_core_configfs.c linux-libre-3.6.3-gnu/drivers/target/target_core_configfs.c
--- linux-libre-3.6-gnu/drivers/target/target_core_configfs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/target_core_configfs.c	2012-10-21 12:32:56.000000000 -0400
@@ -3132,6 +3132,7 @@
 				GFP_KERNEL);
 	if (!target_cg->default_groups) {
 		pr_err("Unable to allocate target_cg->default_groups\n");
+		ret = -ENOMEM;
 		goto out_global;
 	}
 
@@ -3147,6 +3148,7 @@
 				GFP_KERNEL);
 	if (!hba_cg->default_groups) {
 		pr_err("Unable to allocate hba_cg->default_groups\n");
+		ret = -ENOMEM;
 		goto out_global;
 	}
 	config_group_init_type_name(&alua_group,
@@ -3162,6 +3164,7 @@
 			GFP_KERNEL);
 	if (!alua_cg->default_groups) {
 		pr_err("Unable to allocate alua_cg->default_groups\n");
+		ret = -ENOMEM;
 		goto out_global;
 	}
 
@@ -3173,14 +3176,17 @@
 	 * Add core/alua/lu_gps/default_lu_gp
 	 */
 	lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1);
-	if (IS_ERR(lu_gp))
+	if (IS_ERR(lu_gp)) {
+		ret = -ENOMEM;
 		goto out_global;
+	}
 
 	lu_gp_cg = &alua_lu_gps_group;
 	lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 			GFP_KERNEL);
 	if (!lu_gp_cg->default_groups) {
 		pr_err("Unable to allocate lu_gp_cg->default_groups\n");
+		ret = -ENOMEM;
 		goto out_global;
 	}
 
diff -druN linux-libre-3.6-gnu/drivers/target/target_core_file.c linux-libre-3.6.3-gnu/drivers/target/target_core_file.c
--- linux-libre-3.6-gnu/drivers/target/target_core_file.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/target_core_file.c	2012-10-21 12:32:56.000000000 -0400
@@ -125,6 +125,19 @@
 	 * of pure timestamp updates.
 	 */
 	flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;
+	/*
+	 * Optionally allow fd_buffered_io=1 to be enabled for people
+	 * who want use the fs buffer cache as an WriteCache mechanism.
+	 *
+	 * This means that in event of a hard failure, there is a risk
+	 * of silent data-loss if the SCSI client has *not* performed a
+	 * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE
+	 * to write-out the entire device cache.
+	 */
+	if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
+		pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n");
+		flags &= ~O_DSYNC;
+	}
 
 	file = filp_open(fd_dev->fd_dev_name, flags, 0600);
 	if (IS_ERR(file)) {
@@ -188,6 +201,12 @@
 	if (!dev)
 		goto fail;
 
+	if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
+		pr_debug("FILEIO: Forcing setting of emulate_write_cache=1"
+			" with FDBD_HAS_BUFFERED_IO_WCE\n");
+		dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1;
+	}
+
 	fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;
 	fd_dev->fd_queue_depth = dev->queue_depth;
 
@@ -407,6 +426,7 @@
 static match_table_t tokens = {
 	{Opt_fd_dev_name, "fd_dev_name=%s"},
 	{Opt_fd_dev_size, "fd_dev_size=%s"},
+	{Opt_fd_buffered_io, "fd_buffered_io=%d"},
 	{Opt_err, NULL}
 };
 
@@ -418,7 +438,7 @@
 	struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
 	char *orig, *ptr, *arg_p, *opts;
 	substring_t args[MAX_OPT_ARGS];
-	int ret = 0, token;
+	int ret = 0, arg, token;
 
 	opts = kstrdup(page, GFP_KERNEL);
 	if (!opts)
@@ -459,6 +479,19 @@
 					" bytes\n", fd_dev->fd_dev_size);
 			fd_dev->fbd_flags |= FBDF_HAS_SIZE;
 			break;
+		case Opt_fd_buffered_io:
+			match_int(args, &arg);
+			if (arg != 1) {
+				pr_err("bogus fd_buffered_io=%d value\n", arg);
+				ret = -EINVAL;
+				goto out;
+			}
+
+			pr_debug("FILEIO: Using buffered I/O"
+				" operations for struct fd_dev\n");
+
+			fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE;
+			break;
 		default:
 			break;
 		}
@@ -490,8 +523,10 @@
 	ssize_t bl = 0;
 
 	bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id);
-	bl += sprintf(b + bl, "        File: %s  Size: %llu  Mode: O_DSYNC\n",
-		fd_dev->fd_dev_name, fd_dev->fd_dev_size);
+	bl += sprintf(b + bl, "        File: %s  Size: %llu  Mode: %s\n",
+		fd_dev->fd_dev_name, fd_dev->fd_dev_size,
+		(fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ?
+		"Buffered-WCE" : "O_DSYNC");
 	return bl;
 }
 
diff -druN linux-libre-3.6-gnu/drivers/target/target_core_file.h linux-libre-3.6.3-gnu/drivers/target/target_core_file.h
--- linux-libre-3.6-gnu/drivers/target/target_core_file.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/target_core_file.h	2012-10-21 12:32:56.000000000 -0400
@@ -14,6 +14,7 @@
 
 #define FBDF_HAS_PATH		0x01
 #define FBDF_HAS_SIZE		0x02
+#define FDBD_HAS_BUFFERED_IO_WCE 0x04
 
 struct fd_dev {
 	u32		fbd_flags;
diff -druN linux-libre-3.6-gnu/drivers/target/target_core_spc.c linux-libre-3.6.3-gnu/drivers/target/target_core_spc.c
--- linux-libre-3.6-gnu/drivers/target/target_core_spc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/target/target_core_spc.c	2012-10-21 12:32:56.000000000 -0400
@@ -600,30 +600,11 @@
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
-	unsigned char *buf, *map_buf;
+	unsigned char *rbuf;
 	unsigned char *cdb = cmd->t_task_cdb;
+	unsigned char buf[SE_INQUIRY_BUF];
 	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
@@ -655,11 +636,11 @@
 	ret = -EINVAL;
 
 out:
-	if (buf != map_buf) {
-		memcpy(map_buf, buf, cmd->data_length);
-		kfree(buf);
+	rbuf = transport_kmap_data_sg(cmd);
+	if (rbuf) {
+		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+		transport_kunmap_data_sg(cmd);
 	}
-	transport_kunmap_data_sg(cmd);
 
 	if (!ret)
 		target_complete_cmd(cmd, GOOD);
@@ -803,7 +784,7 @@
 	unsigned char *rbuf;
 	int type = dev->transport->get_device_type(dev);
 	int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
-	int offset = ten ? 8 : 4;
+	u32 offset = ten ? 8 : 4;
 	int length = 0;
 	unsigned char buf[SE_MODE_PAGE_BUF];
 
@@ -836,6 +817,7 @@
 		offset -= 2;
 		buf[0] = (offset >> 8) & 0xff;
 		buf[1] = offset & 0xff;
+		offset += 2;
 
 		if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
 		    (cmd->se_deve &&
@@ -845,13 +827,10 @@
 		if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
 		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
 			spc_modesense_dpofua(&buf[3], type);
-
-		if ((offset + 2) > cmd->data_length)
-			offset = cmd->data_length;
-
 	} else {
 		offset -= 1;
 		buf[0] = offset & 0xff;
+		offset += 1;
 
 		if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
 		    (cmd->se_deve &&
@@ -861,14 +840,13 @@
 		if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
 		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
 			spc_modesense_dpofua(&buf[2], type);
-
-		if ((offset + 1) > cmd->data_length)
-			offset = cmd->data_length;
 	}
 
 	rbuf = transport_kmap_data_sg(cmd);
-	memcpy(rbuf, buf, offset);
-	transport_kunmap_data_sg(cmd);
+	if (rbuf) {
+		memcpy(rbuf, buf, min(offset, cmd->data_length));
+		transport_kunmap_data_sg(cmd);
+	}
 
 	target_complete_cmd(cmd, GOOD);
 	return 0;
diff -druN linux-libre-3.6-gnu/drivers/tty/n_gsm.c linux-libre-3.6.3-gnu/drivers/tty/n_gsm.c
--- linux-libre-3.6-gnu/drivers/tty/n_gsm.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/n_gsm.c	2012-10-21 12:32:56.000000000 -0400
@@ -875,7 +875,7 @@
 
 	/* dlci->skb is locked by tx_lock */
 	if (dlci->skb == NULL) {
-		dlci->skb = skb_dequeue(&dlci->skb_list);
+		dlci->skb = skb_dequeue_tail(&dlci->skb_list);
 		if (dlci->skb == NULL)
 			return 0;
 		first = 1;
@@ -899,8 +899,11 @@
 
 	/* FIXME: need a timer or something to kick this so it can't
 	   get stuck with no work outstanding and no buffer free */
-	if (msg == NULL)
+	if (msg == NULL) {
+		skb_queue_tail(&dlci->skb_list, dlci->skb);
+		dlci->skb = NULL;
 		return -ENOMEM;
+	}
 	dp = msg->data;
 
 	if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */
@@ -971,16 +974,19 @@
 static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
 {
 	unsigned long flags;
+	int sweep;
 
 	spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
 	/* If we have nothing running then we need to fire up */
+	sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO);
 	if (dlci->gsm->tx_bytes == 0) {
 		if (dlci->net)
 			gsm_dlci_data_output_framed(dlci->gsm, dlci);
 		else
 			gsm_dlci_data_output(dlci->gsm, dlci);
-	} else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
-		gsm_dlci_data_sweep(dlci->gsm);
+	}
+	if (sweep)
+ 		gsm_dlci_data_sweep(dlci->gsm);
 	spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
 }
 
@@ -1190,6 +1196,8 @@
 							u8 *data, int clen)
 {
 	u8 buf[1];
+	unsigned long flags;
+
 	switch (command) {
 	case CMD_CLD: {
 		struct gsm_dlci *dlci = gsm->dlci[0];
@@ -1215,7 +1223,9 @@
 		gsm->constipated = 0;
 		gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);
 		/* Kick the link in case it is idling */
+		spin_lock_irqsave(&gsm->tx_lock, flags);
 		gsm_data_kick(gsm);
+		spin_unlock_irqrestore(&gsm->tx_lock, flags);
 		break;
 	case CMD_MSC:
 		/* Out of band modem line change indicator for a DLCI */
@@ -2377,12 +2387,12 @@
 
 	/* Queue poll */
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	spin_lock_irqsave(&gsm->tx_lock, flags);
 	gsm_data_kick(gsm);
 	if (gsm->tx_bytes < TX_THRESH_LO) {
-		spin_lock_irqsave(&gsm->tx_lock, flags);
 		gsm_dlci_data_sweep(gsm);
-		spin_unlock_irqrestore(&gsm->tx_lock, flags);
 	}
+	spin_unlock_irqrestore(&gsm->tx_lock, flags);
 }
 
 /**
@@ -2889,6 +2899,10 @@
 	gsm = gsm_mux[mux];
 	if (gsm->dead)
 		return -EL2HLT;
+	/* If DLCI 0 is not yet fully open return an error. This is ok from a locking
+	   perspective as we don't have to worry about this if DLCI0 is lost */
+	if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
+		return -EL2NSYNC;
 	dlci = gsm->dlci[line];
 	if (dlci == NULL)
 		dlci = gsm_dlci_alloc(gsm, line);
diff -druN linux-libre-3.6-gnu/drivers/tty/n_tty.c linux-libre-3.6.3-gnu/drivers/tty/n_tty.c
--- linux-libre-3.6-gnu/drivers/tty/n_tty.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/n_tty.c	2012-10-21 12:32:56.000000000 -0400
@@ -1728,7 +1728,8 @@
 
 do_it_again:
 
-	BUG_ON(!tty->read_buf);
+	if (WARN_ON(!tty->read_buf))
+		return -EAGAIN;
 
 	c = job_control(tty, file);
 	if (c < 0)
diff -druN linux-libre-3.6-gnu/drivers/tty/serial/8250/8250_pci.c linux-libre-3.6.3-gnu/drivers/tty/serial/8250/8250_pci.c
--- linux-libre-3.6-gnu/drivers/tty/serial/8250/8250_pci.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/serial/8250/8250_pci.c	2012-10-21 12:32:56.000000000 -0400
@@ -1164,6 +1164,8 @@
 #define PCI_SUBDEVICE_ID_OCTPRO422	0x0208
 #define PCI_SUBDEVICE_ID_POCTAL232	0x0308
 #define PCI_SUBDEVICE_ID_POCTAL422	0x0408
+#define PCI_SUBDEVICE_ID_SIIG_DUAL_00	0x2500
+#define PCI_SUBDEVICE_ID_SIIG_DUAL_30	0x2530
 #define PCI_VENDOR_ID_ADVANTECH		0x13fe
 #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
 #define PCI_DEVICE_ID_ADVANTECH_PCI3620	0x3620
@@ -3232,8 +3234,11 @@
 		 * For now just used the hex ID 0x950a.
 		 */
 	{	PCI_VENDOR_ID_OXSEMI, 0x950a,
-		PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
-		pbn_b0_2_115200 },
+		PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00,
+		0, 0, pbn_b0_2_115200 },
+	{	PCI_VENDOR_ID_OXSEMI, 0x950a,
+		PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30,
+		0, 0, pbn_b0_2_115200 },
 	{	PCI_VENDOR_ID_OXSEMI, 0x950a,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b0_2_1130000 },
diff -druN linux-libre-3.6-gnu/drivers/tty/serial/amba-pl011.c linux-libre-3.6.3-gnu/drivers/tty/serial/amba-pl011.c
--- linux-libre-3.6-gnu/drivers/tty/serial/amba-pl011.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/serial/amba-pl011.c	2012-10-21 12:32:56.000000000 -0400
@@ -1603,13 +1603,26 @@
 			old_cr &= ~ST_UART011_CR_OVSFACT;
 	}
 
+	/*
+	 * Workaround for the ST Micro oversampling variants to
+	 * increase the bitrate slightly, by lowering the divisor,
+	 * to avoid delayed sampling of start bit at high speeds,
+	 * else we see data corruption.
+	 */
+	if (uap->vendor->oversampling) {
+		if ((baud >= 3000000) && (baud < 3250000) && (quot > 1))
+			quot -= 1;
+		else if ((baud > 3250000) && (quot > 2))
+			quot -= 2;
+	}
 	/* Set baud rate */
 	writew(quot & 0x3f, port->membase + UART011_FBRD);
 	writew(quot >> 6, port->membase + UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
-	 * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
+	 * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
+	 * UART011_FBRD & UART011_IBRD.
 	 * ----------^----------^----------^----------^-----
 	 */
 	writew(lcr_h, port->membase + uap->lcrh_rx);
diff -druN linux-libre-3.6-gnu/drivers/tty/serial/omap-serial.c linux-libre-3.6.3-gnu/drivers/tty/serial/omap-serial.c
--- linux-libre-3.6-gnu/drivers/tty/serial/omap-serial.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/serial/omap-serial.c	2012-10-21 12:32:56.000000000 -0400
@@ -667,19 +667,19 @@
 
 	/*
 	 * IXON Flag:
-	 * Enable XON/XOFF flow control on output.
-	 * Transmit XON1, XOFF1
+	 * Flow control for OMAP.TX
+	 * OMAP.RX should listen for XON/XOFF
 	 */
 	if (termios->c_iflag & IXON)
-		up->efr |= OMAP_UART_SW_TX;
+		up->efr |= OMAP_UART_SW_RX;
 
 	/*
 	 * IXOFF Flag:
-	 * Enable XON/XOFF flow control on input.
-	 * Receiver compares XON1, XOFF1.
+	 * Flow control for OMAP.RX
+	 * OMAP.TX should send XON/XOFF
 	 */
 	if (termios->c_iflag & IXOFF)
-		up->efr |= OMAP_UART_SW_RX;
+		up->efr |= OMAP_UART_SW_TX;
 
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
diff -druN linux-libre-3.6-gnu/drivers/tty/vt/keyboard.c linux-libre-3.6.3-gnu/drivers/tty/vt/keyboard.c
--- linux-libre-3.6-gnu/drivers/tty/vt/keyboard.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/vt/keyboard.c	2012-10-21 12:32:56.000000000 -0400
@@ -1049,13 +1049,10 @@
  */
 int vt_get_leds(int console, int flag)
 {
-	unsigned long flags;
 	struct kbd_struct * kbd = kbd_table + console;
 	int ret;
 
-	spin_lock_irqsave(&kbd_event_lock, flags);
 	ret = vc_kbd_led(kbd, flag);
-	spin_unlock_irqrestore(&kbd_event_lock, flags);
 
 	return ret;
 }
diff -druN linux-libre-3.6-gnu/drivers/tty/vt/vt.c linux-libre-3.6.3-gnu/drivers/tty/vt/vt.c
--- linux-libre-3.6-gnu/drivers/tty/vt/vt.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/tty/vt/vt.c	2012-10-21 12:32:56.000000000 -0400
@@ -3475,6 +3475,19 @@
 			kdb_set(2, setargs);
 		}
 	}
+	if (vc->vc_cols < 999) {
+		int colcount;
+		char cols[4];
+		const char *setargs[3] = {
+			"set",
+			"COLUMNS",
+			cols,
+		};
+		if (kdbgetintenv(setargs[0], &colcount)) {
+			snprintf(cols, 4, "%i", vc->vc_cols);
+			kdb_set(2, setargs);
+		}
+	}
 #endif /* CONFIG_KGDB_KDB */
 	return ret;
 }
diff -druN linux-libre-3.6-gnu/drivers/usb/class/cdc-acm.c linux-libre-3.6.3-gnu/drivers/usb/class/cdc-acm.c
--- linux-libre-3.6-gnu/drivers/usb/class/cdc-acm.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/class/cdc-acm.c	2012-10-21 12:32:56.000000000 -0400
@@ -1551,6 +1551,9 @@
 					   Maybe we should define a new
 					   quirk for this. */
 	},
+	{ USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */
+	.driver_info = NO_UNION_NORMAL,
+	},
 	{ USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
 	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
 	},
diff -druN linux-libre-3.6-gnu/drivers/usb/gadget/at91_udc.c linux-libre-3.6.3-gnu/drivers/usb/gadget/at91_udc.c
--- linux-libre-3.6-gnu/drivers/usb/gadget/at91_udc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/gadget/at91_udc.c	2012-10-21 12:32:56.000000000 -0400
@@ -1699,7 +1699,7 @@
 	int		retval;
 	struct resource	*res;
 
-	if (!dev->platform_data) {
+	if (!dev->platform_data && !pdev->dev.of_node) {
 		/* small (so we copy it) but critical! */
 		DBG("missing platform_data\n");
 		return -ENODEV;
diff -druN linux-libre-3.6-gnu/drivers/usb/gadget/printer.c linux-libre-3.6.3-gnu/drivers/usb/gadget/printer.c
--- linux-libre-3.6-gnu/drivers/usb/gadget/printer.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/gadget/printer.c	2012-10-21 12:32:56.000000000 -0400
@@ -141,18 +141,14 @@
  * descriptors are built on demand.
  */
 
-#define STRING_MANUFACTURER		1
-#define STRING_PRODUCT			2
-#define STRING_SERIALNUM		3
+#define STRING_MANUFACTURER		0
+#define STRING_PRODUCT			1
+#define STRING_SERIALNUM		2
 
 /* holds our biggest descriptor */
 #define USB_DESC_BUFSIZE		256
 #define USB_BUFSIZE			8192
 
-/* This device advertises one configuration. */
-#define DEV_CONFIG_VALUE		1
-#define	PRINTER_INTERFACE		0
-
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
@@ -162,16 +158,12 @@
 	.bDeviceProtocol =	0,
 	.idVendor =		cpu_to_le16(PRINTER_VENDOR_NUM),
 	.idProduct =		cpu_to_le16(PRINTER_PRODUCT_NUM),
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
-	.iSerialNumber =	STRING_SERIALNUM,
 	.bNumConfigurations =	1
 };
 
 static struct usb_interface_descriptor intf_desc = {
 	.bLength =		sizeof intf_desc,
 	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	PRINTER_INTERFACE,
 	.bNumEndpoints =	2,
 	.bInterfaceClass =	USB_CLASS_PRINTER,
 	.bInterfaceSubClass =	1,	/* Printer Sub-Class */
@@ -260,9 +252,9 @@
 
 /* static strings, in UTF-8 */
 static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER,	manufacturer, },
-	{ STRING_PRODUCT,	product_desc, },
-	{ STRING_SERIALNUM,	serial_num, },
+	[STRING_MANUFACTURER].s = manufacturer,
+	[STRING_PRODUCT].s = product_desc,
+	[STRING_SERIALNUM].s =	serial_num,
 	{  }		/* end of list */
 };
 
@@ -871,25 +863,13 @@
 	int			result = 0;
 
 	/* Free the current interface */
-	switch (dev->interface) {
-	case PRINTER_INTERFACE:
-		printer_reset_interface(dev);
-		break;
-	}
+	printer_reset_interface(dev);
 
-	switch (number) {
-	case PRINTER_INTERFACE:
-		result = set_printer_interface(dev);
-		if (result) {
-			printer_reset_interface(dev);
-		} else {
-			dev->interface = PRINTER_INTERFACE;
-		}
-		break;
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	}
+	result = set_printer_interface(dev);
+	if (result)
+		printer_reset_interface(dev);
+	else
+		dev->interface = number;
 
 	if (!result)
 		INFO(dev, "Using interface %x\n", number);
@@ -972,7 +952,7 @@
 		switch (ctrl->bRequest) {
 		case 0: /* Get the IEEE-1284 PNP String */
 			/* Only one printer interface is supported. */
-			if ((wIndex>>8) != PRINTER_INTERFACE)
+			if ((wIndex>>8) != dev->interface)
 				break;
 
 			value = (pnp_string[0]<<8)|pnp_string[1];
@@ -983,7 +963,7 @@
 
 		case 1: /* Get Port Status */
 			/* Only one printer interface is supported. */
-			if (wIndex != PRINTER_INTERFACE)
+			if (wIndex != dev->interface)
 				break;
 
 			*(u8 *)req->buf = dev->printer_status;
@@ -992,7 +972,7 @@
 
 		case 2: /* Soft Reset */
 			/* Only one printer interface is supported. */
-			if (wIndex != PRINTER_INTERFACE)
+			if (wIndex != dev->interface)
 				break;
 
 			printer_soft_reset(dev);
@@ -1020,6 +1000,37 @@
 static int __init printer_func_bind(struct usb_configuration *c,
 		struct usb_function *f)
 {
+	struct printer_dev *dev = container_of(f, struct printer_dev, function);
+	struct usb_composite_dev *cdev = c->cdev;
+	struct usb_ep		*in_ep, *out_ep;
+	int id;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	intf_desc.bInterfaceNumber = id;
+
+	/* all we really need is bulk IN/OUT */
+	in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc);
+	if (!in_ep) {
+autoconf_fail:
+		dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n",
+			cdev->gadget->name);
+		return -ENODEV;
+	}
+	in_ep->driver_data = in_ep;	/* claim */
+
+	out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
+	if (!out_ep)
+		goto autoconf_fail;
+	out_ep->driver_data = out_ep;	/* claim */
+
+	/* assumes that all endpoints are dual-speed */
+	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
+	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
+
+	dev->in_ep = in_ep;
+	dev->out_ep = out_ep;
 	return 0;
 }
 
@@ -1035,7 +1046,8 @@
 	int ret = -ENOTSUPP;
 
 	if (!alt)
-		ret = set_interface(dev, PRINTER_INTERFACE);
+		ret = set_interface(dev, intf);
+
 	return ret;
 }
 
@@ -1107,13 +1119,14 @@
 {
 	struct usb_gadget	*gadget = c->cdev->gadget;
 	struct printer_dev	*dev;
-	struct usb_ep		*in_ep, *out_ep;
 	int			status = -ENOMEM;
 	int			gcnum;
 	size_t			len;
 	u32			i;
 	struct usb_request	*req;
 
+	usb_ep_autoconfig_reset(gadget);
+
 	dev = &usb_printer_gadget;
 
 	dev->function.name = shortname;
@@ -1125,6 +1138,10 @@
 	dev->function.set_alt = printer_func_set_alt;
 	dev->function.disable = printer_func_disable;
 
+	status = usb_add_function(c, &dev->function);
+	if (status)
+		return status;
+
 	/* Setup the sysfs files for the printer gadget. */
 	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
 				  NULL, "g_printer");
@@ -1169,26 +1186,6 @@
 	pnp_string[0] = (len >> 8) & 0xFF;
 	pnp_string[1] = len & 0xFF;
 
-	/* all we really need is bulk IN/OUT */
-	usb_ep_autoconfig_reset(gadget);
-	in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc);
-	if (!in_ep) {
-autoconf_fail:
-		dev_err(&gadget->dev, "can't autoconfigure on %s\n",
-			gadget->name);
-		return -ENODEV;
-	}
-	in_ep->driver_data = in_ep;	/* claim */
-
-	out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc);
-	if (!out_ep)
-		goto autoconf_fail;
-	out_ep->driver_data = out_ep;	/* claim */
-
-	/* assumes that all endpoints are dual-speed */
-	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
-	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
-
 	usb_gadget_set_selfpowered(gadget);
 
 	if (gadget->is_otg) {
@@ -1215,9 +1212,6 @@
 	dev->current_rx_bytes = 0;
 	dev->current_rx_buf = NULL;
 
-	dev->in_ep = in_ep;
-	dev->out_ep = out_ep;
-
 	for (i = 0; i < QLEN; i++) {
 		req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
 		if (!req) {
@@ -1250,8 +1244,6 @@
 	dev->gadget = gadget;
 
 	INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
-	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
-			in_ep->name);
 	return 0;
 
 fail:
@@ -1266,7 +1258,17 @@
 
 static int __init printer_bind(struct usb_composite_dev *cdev)
 {
-	return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
+	int ret;
+
+	ret = usb_string_ids_tab(cdev, strings);
+	if (ret < 0)
+		return ret;
+	device_desc.iManufacturer = strings[STRING_MANUFACTURER].id;
+	device_desc.iProduct = strings[STRING_PRODUCT].id;
+	device_desc.iSerialNumber = strings[STRING_SERIALNUM].id;
+
+	ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
+	return ret;
 }
 
 static struct usb_composite_driver printer_driver = {
diff -druN linux-libre-3.6-gnu/drivers/usb/gadget/tcm_usb_gadget.c linux-libre-3.6.3-gnu/drivers/usb/gadget/tcm_usb_gadget.c
--- linux-libre-3.6-gnu/drivers/usb/gadget/tcm_usb_gadget.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/gadget/tcm_usb_gadget.c	2012-10-21 12:32:56.000000000 -0400
@@ -1977,7 +1977,6 @@
 	.bInterfaceClass =      USB_CLASS_MASS_STORAGE,
 	.bInterfaceSubClass =   USB_SC_SCSI,
 	.bInterfaceProtocol =   USB_PR_BULK,
-	.iInterface =           USB_G_STR_INT_UAS,
 };
 
 static struct usb_interface_descriptor uasp_intf_desc = {
@@ -1988,7 +1987,6 @@
 	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
 	.bInterfaceSubClass =	USB_SC_SCSI,
 	.bInterfaceProtocol =	USB_PR_UAS,
-	.iInterface =		USB_G_STR_INT_BBB,
 };
 
 static struct usb_endpoint_descriptor uasp_bi_desc = {
@@ -2209,20 +2207,16 @@
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 	.idVendor =		cpu_to_le16(UAS_VENDOR_ID),
 	.idProduct =		cpu_to_le16(UAS_PRODUCT_ID),
-	.iManufacturer =	USB_G_STR_MANUFACTOR,
-	.iProduct =		USB_G_STR_PRODUCT,
-	.iSerialNumber =	USB_G_STR_SERIAL,
-
 	.bNumConfigurations =   1,
 };
 
 static struct usb_string	usbg_us_strings[] = {
-	{ USB_G_STR_MANUFACTOR,	"Target Manufactor"},
-	{ USB_G_STR_PRODUCT,	"Target Product"},
-	{ USB_G_STR_SERIAL,	"000000000001"},
-	{ USB_G_STR_CONFIG,	"default config"},
-	{ USB_G_STR_INT_UAS,	"USB Attached SCSI"},
-	{ USB_G_STR_INT_BBB,	"Bulk Only Transport"},
+	[USB_G_STR_MANUFACTOR].s	= "Target Manufactor",
+	[USB_G_STR_PRODUCT].s		= "Target Product",
+	[USB_G_STR_SERIAL].s		= "000000000001",
+	[USB_G_STR_CONFIG].s		= "default config",
+	[USB_G_STR_INT_UAS].s		= "USB Attached SCSI",
+	[USB_G_STR_INT_BBB].s		= "Bulk Only Transport",
 	{ },
 };
 
@@ -2244,7 +2238,6 @@
 static struct usb_configuration usbg_config_driver = {
 	.label                  = "Linux Target",
 	.bConfigurationValue    = 1,
-	.iConfiguration		= USB_G_STR_CONFIG,
 	.bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
 };
 
@@ -2417,6 +2410,9 @@
 	fu->function.disable = usbg_disable;
 	fu->tpg = the_only_tpg_I_currently_have;
 
+	bot_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_BBB].id;
+	uasp_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_UAS].id;
+
 	ret = usb_add_function(c, &fu->function);
 	if (ret)
 		goto err;
@@ -2431,6 +2427,17 @@
 {
 	int ret;
 
+	ret = usb_string_ids_tab(cdev, usbg_us_strings);
+	if (ret)
+		return ret;
+
+	usbg_device_desc.iManufacturer =
+		usbg_us_strings[USB_G_STR_MANUFACTOR].id;
+	usbg_device_desc.iProduct = usbg_us_strings[USB_G_STR_PRODUCT].id;
+	usbg_device_desc.iSerialNumber = usbg_us_strings[USB_G_STR_SERIAL].id;
+	usbg_config_driver.iConfiguration =
+		usbg_us_strings[USB_G_STR_CONFIG].id;
+
 	ret = usb_add_config(cdev, &usbg_config_driver,
 			usbg_cfg_bind);
 	return 0;
diff -druN linux-libre-3.6-gnu/drivers/usb/gadget/tcm_usb_gadget.h linux-libre-3.6.3-gnu/drivers/usb/gadget/tcm_usb_gadget.h
--- linux-libre-3.6-gnu/drivers/usb/gadget/tcm_usb_gadget.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/gadget/tcm_usb_gadget.h	2012-10-21 12:32:56.000000000 -0400
@@ -16,12 +16,14 @@
 #define UASP_SS_EP_COMP_LOG_STREAMS 4
 #define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS)
 
-#define USB_G_STR_MANUFACTOR    1
-#define USB_G_STR_PRODUCT       2
-#define USB_G_STR_SERIAL        3
-#define USB_G_STR_CONFIG        4
-#define USB_G_STR_INT_UAS       5
-#define USB_G_STR_INT_BBB       6
+enum {
+	USB_G_STR_MANUFACTOR,
+	USB_G_STR_PRODUCT,
+	USB_G_STR_SERIAL,
+	USB_G_STR_CONFIG,
+	USB_G_STR_INT_UAS,
+	USB_G_STR_INT_BBB,
+};
 
 #define USB_G_ALT_INT_BBB       0
 #define USB_G_ALT_INT_UAS       1
diff -druN linux-libre-3.6-gnu/drivers/usb/host/ehci-timer.c linux-libre-3.6.3-gnu/drivers/usb/host/ehci-timer.c
--- linux-libre-3.6-gnu/drivers/usb/host/ehci-timer.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/host/ehci-timer.c	2012-10-21 12:32:56.000000000 -0400
@@ -118,7 +118,8 @@
 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
 			return;
 		}
-		ehci_warn(ehci, "Waited too long for the async schedule status, giving up\n");
+		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
+				want, actual);
 	}
 	ehci->ASS_poll_count = 0;
 
@@ -163,7 +164,8 @@
 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
 			return;
 		}
-		ehci_warn(ehci, "Waited too long for the periodic schedule status, giving up\n");
+		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
+				want, actual);
 	}
 	ehci->PSS_poll_count = 0;
 
diff -druN linux-libre-3.6-gnu/drivers/usb/host/xhci.c linux-libre-3.6.3-gnu/drivers/usb/host/xhci.c
--- linux-libre-3.6-gnu/drivers/usb/host/xhci.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/host/xhci.c	2012-10-21 12:32:56.000000000 -0400
@@ -52,7 +52,7 @@
  * handshake done).  There are two failure modes:  "usec" have passed (major
  * hardware flakeout), or the register reads as all-ones (hardware removed).
  */
-static int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
 		      u32 mask, u32 done, int usec)
 {
 	u32	result;
@@ -105,9 +105,10 @@
 
 	ret = handshake(xhci, &xhci->op_regs->status,
 			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
-	if (!ret)
+	if (!ret) {
 		xhci->xhc_state |= XHCI_STATE_HALTED;
-	else
+		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+	} else
 		xhci_warn(xhci, "Host not halted after %u microseconds.\n",
 				XHCI_MAX_HALT_USEC);
 	return ret;
@@ -470,6 +471,8 @@
 
 	dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
 	dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+	if (!dmi_product_name || !dmi_sys_vendor)
+		return false;
 
 	if (!(strstr(dmi_sys_vendor, "Hewlett-Packard")))
 		return false;
@@ -581,6 +584,7 @@
 		return -ENODEV;
 	}
 	xhci->shared_hcd->state = HC_STATE_RUNNING;
+	xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
 
 	if (xhci->quirks & XHCI_NEC_HOST)
 		xhci_ring_cmd_db(xhci);
@@ -886,7 +890,7 @@
 	command &= ~CMD_RUN;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
 	if (handshake(xhci, &xhci->op_regs->status,
-		      STS_HALT, STS_HALT, 100*100)) {
+		      STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
 		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
 		spin_unlock_irq(&xhci->lock);
 		return -ETIMEDOUT;
@@ -2521,6 +2525,7 @@
 	struct completion *cmd_completion;
 	u32 *cmd_status;
 	struct xhci_virt_device *virt_dev;
+	union xhci_trb *cmd_trb;
 
 	spin_lock_irqsave(&xhci->lock, flags);
 	virt_dev = xhci->devs[udev->slot_id];
@@ -2566,6 +2571,7 @@
 	}
 	init_completion(cmd_completion);
 
+	cmd_trb = xhci->cmd_ring->dequeue;
 	if (!ctx_change)
 		ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
 				udev->slot_id, must_succeed);
@@ -2587,14 +2593,17 @@
 	/* Wait for the configure endpoint command to complete */
 	timeleft = wait_for_completion_interruptible_timeout(
 			cmd_completion,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for %s command\n",
 				timeleft == 0 ? "Timeout" : "Signal",
 				ctx_change == 0 ?
 					"configure endpoint" :
 					"evaluate context");
-		/* FIXME cancel the configure endpoint command */
+		/* cancel the configure endpoint command */
+		ret = xhci_cancel_cmd(xhci, command, cmd_trb);
+		if (ret < 0)
+			return ret;
 		return -ETIME;
 	}
 
@@ -3543,8 +3552,10 @@
 	unsigned long flags;
 	int timeleft;
 	int ret;
+	union xhci_trb *cmd_trb;
 
 	spin_lock_irqsave(&xhci->lock, flags);
+	cmd_trb = xhci->cmd_ring->dequeue;
 	ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
 	if (ret) {
 		spin_unlock_irqrestore(&xhci->lock, flags);
@@ -3556,12 +3567,12 @@
 
 	/* XXX: how much time for xHC slot assignment? */
 	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for a slot\n",
 				timeleft == 0 ? "Timeout" : "Signal");
-		/* FIXME cancel the enable slot request */
-		return 0;
+		/* cancel the enable slot request */
+		return xhci_cancel_cmd(xhci, NULL, cmd_trb);
 	}
 
 	if (!xhci->slot_id) {
@@ -3622,6 +3633,7 @@
 	struct xhci_slot_ctx *slot_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
 	u64 temp_64;
+	union xhci_trb *cmd_trb;
 
 	if (!udev->slot_id) {
 		xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
@@ -3660,6 +3672,7 @@
 	xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
 	spin_lock_irqsave(&xhci->lock, flags);
+	cmd_trb = xhci->cmd_ring->dequeue;
 	ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
 					udev->slot_id);
 	if (ret) {
@@ -3672,7 +3685,7 @@
 
 	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
 	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
 	 * the SetAddress() "recovery interval" required by USB and aborting the
 	 * command on a timeout.
@@ -3680,7 +3693,10 @@
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for address device command\n",
 				timeleft == 0 ? "Timeout" : "Signal");
-		/* FIXME cancel the address device command */
+		/* cancel the address device command */
+		ret = xhci_cancel_cmd(xhci, NULL, cmd_trb);
+		if (ret < 0)
+			return ret;
 		return -ETIME;
 	}
 
diff -druN linux-libre-3.6-gnu/drivers/usb/host/xhci.h linux-libre-3.6.3-gnu/drivers/usb/host/xhci.h
--- linux-libre-3.6-gnu/drivers/usb/host/xhci.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/host/xhci.h	2012-10-21 12:32:56.000000000 -0400
@@ -1256,6 +1256,16 @@
 	union xhci_trb		*last_trb;
 };
 
+/* xHCI command default timeout value */
+#define XHCI_CMD_DEFAULT_TIMEOUT	(5 * HZ)
+
+/* command descriptor */
+struct xhci_cd {
+	struct list_head	cancel_cmd_list;
+	struct xhci_command	*command;
+	union xhci_trb		*cmd_trb;
+};
+
 struct xhci_dequeue_state {
 	struct xhci_segment *new_deq_seg;
 	union xhci_trb *new_deq_ptr;
@@ -1421,6 +1431,11 @@
 	/* data structures */
 	struct xhci_device_context_array *dcbaa;
 	struct xhci_ring	*cmd_ring;
+	unsigned int            cmd_ring_state;
+#define CMD_RING_STATE_RUNNING         (1 << 0)
+#define CMD_RING_STATE_ABORTED         (1 << 1)
+#define CMD_RING_STATE_STOPPED         (1 << 2)
+	struct list_head        cancel_cmd_list;
 	unsigned int		cmd_ring_reserved_trbs;
 	struct xhci_ring	*event_ring;
 	struct xhci_erst	erst;
@@ -1496,6 +1511,7 @@
 #define XHCI_INTEL_HOST		(1 << 12)
 #define XHCI_SPURIOUS_REBOOT	(1 << 13)
 #define XHCI_COMP_MODE_QUIRK	(1 << 14)
+#define XHCI_AVOID_BEI		(1 << 15)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
 	/* There are two roothubs to keep track of bus suspend info for */
@@ -1704,6 +1720,8 @@
 
 /* xHCI host controller glue */
 typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
+int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+		u32 mask, u32 done, int usec);
 void xhci_quiesce(struct xhci_hcd *xhci);
 int xhci_halt(struct xhci_hcd *xhci);
 int xhci_reset(struct xhci_hcd *xhci);
@@ -1794,6 +1812,8 @@
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
+int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
+		union xhci_trb *cmd_trb);
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
 		unsigned int ep_index, unsigned int stream_id);
 
diff -druN linux-libre-3.6-gnu/drivers/usb/host/xhci-mem.c linux-libre-3.6.3-gnu/drivers/usb/host/xhci-mem.c
--- linux-libre-3.6-gnu/drivers/usb/host/xhci-mem.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/host/xhci-mem.c	2012-10-21 12:32:56.000000000 -0400
@@ -1772,6 +1772,7 @@
 {
 	struct pci_dev	*pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
 	struct dev_info	*dev_info, *next;
+	struct xhci_cd  *cur_cd, *next_cd;
 	unsigned long	flags;
 	int size;
 	int i, j, num_ports;
@@ -1795,6 +1796,11 @@
 		xhci_ring_free(xhci, xhci->cmd_ring);
 	xhci->cmd_ring = NULL;
 	xhci_dbg(xhci, "Freed command ring\n");
+	list_for_each_entry_safe(cur_cd, next_cd,
+			&xhci->cancel_cmd_list, cancel_cmd_list) {
+		list_del(&cur_cd->cancel_cmd_list);
+		kfree(cur_cd);
+	}
 
 	for (i = 1; i < MAX_HC_SLOTS; ++i)
 		xhci_free_virt_device(xhci, i);
@@ -2340,6 +2346,7 @@
 	xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags);
 	if (!xhci->cmd_ring)
 		goto fail;
+	INIT_LIST_HEAD(&xhci->cancel_cmd_list);
 	xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring);
 	xhci_dbg(xhci, "First segment DMA is 0x%llx\n",
 			(unsigned long long)xhci->cmd_ring->first_seg->dma);
diff -druN linux-libre-3.6-gnu/drivers/usb/host/xhci-pci.c linux-libre-3.6.3-gnu/drivers/usb/host/xhci-pci.c
--- linux-libre-3.6-gnu/drivers/usb/host/xhci-pci.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/host/xhci-pci.c	2012-10-21 12:32:56.000000000 -0400
@@ -103,6 +103,7 @@
 		 * PPT chipsets.
 		 */
 		xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+		xhci->quirks |= XHCI_AVOID_BEI;
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
 			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
diff -druN linux-libre-3.6-gnu/drivers/usb/host/xhci-ring.c linux-libre-3.6.3-gnu/drivers/usb/host/xhci-ring.c
--- linux-libre-3.6-gnu/drivers/usb/host/xhci-ring.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/host/xhci-ring.c	2012-10-21 12:32:56.000000000 -0400
@@ -280,12 +280,123 @@
 /* Ring the host controller doorbell after placing a command on the ring */
 void xhci_ring_cmd_db(struct xhci_hcd *xhci)
 {
+	if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING))
+		return;
+
 	xhci_dbg(xhci, "// Ding dong!\n");
 	xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]);
 	/* Flush PCI posted writes */
 	xhci_readl(xhci, &xhci->dba->doorbell[0]);
 }
 
+static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
+{
+	u64 temp_64;
+	int ret;
+
+	xhci_dbg(xhci, "Abort command ring\n");
+
+	if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) {
+		xhci_dbg(xhci, "The command ring isn't running, "
+				"Have the command ring been stopped?\n");
+		return 0;
+	}
+
+	temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+	if (!(temp_64 & CMD_RING_RUNNING)) {
+		xhci_dbg(xhci, "Command ring had been stopped\n");
+		return 0;
+	}
+	xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
+	xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
+			&xhci->op_regs->cmd_ring);
+
+	/* Section 4.6.1.2 of xHCI 1.0 spec says software should
+	 * time the completion od all xHCI commands, including
+	 * the Command Abort operation. If software doesn't see
+	 * CRR negated in a timely manner (e.g. longer than 5
+	 * seconds), then it should assume that the there are
+	 * larger problems with the xHC and assert HCRST.
+	 */
+	ret = handshake(xhci, &xhci->op_regs->cmd_ring,
+			CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
+	if (ret < 0) {
+		xhci_err(xhci, "Stopped the command ring failed, "
+				"maybe the host is dead\n");
+		xhci->xhc_state |= XHCI_STATE_DYING;
+		xhci_quiesce(xhci);
+		xhci_halt(xhci);
+		return -ESHUTDOWN;
+	}
+
+	return 0;
+}
+
+static int xhci_queue_cd(struct xhci_hcd *xhci,
+		struct xhci_command *command,
+		union xhci_trb *cmd_trb)
+{
+	struct xhci_cd *cd;
+	cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC);
+	if (!cd)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&cd->cancel_cmd_list);
+
+	cd->command = command;
+	cd->cmd_trb = cmd_trb;
+	list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list);
+
+	return 0;
+}
+
+/*
+ * Cancel the command which has issue.
+ *
+ * Some commands may hang due to waiting for acknowledgement from
+ * usb device. It is outside of the xHC's ability to control and
+ * will cause the command ring is blocked. When it occurs software
+ * should intervene to recover the command ring.
+ * See Section 4.6.1.1 and 4.6.1.2
+ */
+int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
+		union xhci_trb *cmd_trb)
+{
+	int retval = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&xhci->lock, flags);
+
+	if (xhci->xhc_state & XHCI_STATE_DYING) {
+		xhci_warn(xhci, "Abort the command ring,"
+				" but the xHCI is dead.\n");
+		retval = -ESHUTDOWN;
+		goto fail;
+	}
+
+	/* queue the cmd desriptor to cancel_cmd_list */
+	retval = xhci_queue_cd(xhci, command, cmd_trb);
+	if (retval) {
+		xhci_warn(xhci, "Queuing command descriptor failed.\n");
+		goto fail;
+	}
+
+	/* abort command ring */
+	retval = xhci_abort_cmd_ring(xhci);
+	if (retval) {
+		xhci_err(xhci, "Abort command ring failed\n");
+		if (unlikely(retval == -ESHUTDOWN)) {
+			spin_unlock_irqrestore(&xhci->lock, flags);
+			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
+			xhci_dbg(xhci, "xHCI host controller is dead.\n");
+			return retval;
+		}
+	}
+
+fail:
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	return retval;
+}
+
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
 		unsigned int slot_id,
 		unsigned int ep_index,
@@ -1059,6 +1170,20 @@
 	}
 }
 
+/* Complete the command and detele it from the devcie's command queue.
+ */
+static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
+		struct xhci_command *command, u32 status)
+{
+	command->status = status;
+	list_del(&command->cmd_list);
+	if (command->completion)
+		complete(command->completion);
+	else
+		xhci_free_command(xhci, command);
+}
+
+
 /* Check to see if a command in the device's command queue matches this one.
  * Signal the completion or free the command, and return 1.  Return 0 if the
  * completed command isn't at the head of the command list.
@@ -1077,15 +1202,144 @@
 	if (xhci->cmd_ring->dequeue != command->command_trb)
 		return 0;
 
-	command->status = GET_COMP_CODE(le32_to_cpu(event->status));
-	list_del(&command->cmd_list);
-	if (command->completion)
-		complete(command->completion);
-	else
-		xhci_free_command(xhci, command);
+	xhci_complete_cmd_in_cmd_wait_list(xhci, command,
+			GET_COMP_CODE(le32_to_cpu(event->status)));
 	return 1;
 }
 
+/*
+ * Finding the command trb need to be cancelled and modifying it to
+ * NO OP command. And if the command is in device's command wait
+ * list, finishing and freeing it.
+ *
+ * If we can't find the command trb, we think it had already been
+ * executed.
+ */
+static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
+{
+	struct xhci_segment *cur_seg;
+	union xhci_trb *cmd_trb;
+	u32 cycle_state;
+
+	if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
+		return;
+
+	/* find the current segment of command ring */
+	cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
+			xhci->cmd_ring->dequeue, &cycle_state);
+
+	/* find the command trb matched by cd from command ring */
+	for (cmd_trb = xhci->cmd_ring->dequeue;
+			cmd_trb != xhci->cmd_ring->enqueue;
+			next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) {
+		/* If the trb is link trb, continue */
+		if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3]))
+			continue;
+
+		if (cur_cd->cmd_trb == cmd_trb) {
+
+			/* If the command in device's command list, we should
+			 * finish it and free the command structure.
+			 */
+			if (cur_cd->command)
+				xhci_complete_cmd_in_cmd_wait_list(xhci,
+					cur_cd->command, COMP_CMD_STOP);
+
+			/* get cycle state from the origin command trb */
+			cycle_state = le32_to_cpu(cmd_trb->generic.field[3])
+				& TRB_CYCLE;
+
+			/* modify the command trb to NO OP command */
+			cmd_trb->generic.field[0] = 0;
+			cmd_trb->generic.field[1] = 0;
+			cmd_trb->generic.field[2] = 0;
+			cmd_trb->generic.field[3] = cpu_to_le32(
+					TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
+			break;
+		}
+	}
+}
+
+static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci)
+{
+	struct xhci_cd *cur_cd, *next_cd;
+
+	if (list_empty(&xhci->cancel_cmd_list))
+		return;
+
+	list_for_each_entry_safe(cur_cd, next_cd,
+			&xhci->cancel_cmd_list, cancel_cmd_list) {
+		xhci_cmd_to_noop(xhci, cur_cd);
+		list_del(&cur_cd->cancel_cmd_list);
+		kfree(cur_cd);
+	}
+}
+
+/*
+ * traversing the cancel_cmd_list. If the command descriptor according
+ * to cmd_trb is found, the function free it and return 1, otherwise
+ * return 0.
+ */
+static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci,
+		union xhci_trb *cmd_trb)
+{
+	struct xhci_cd *cur_cd, *next_cd;
+
+	if (list_empty(&xhci->cancel_cmd_list))
+		return 0;
+
+	list_for_each_entry_safe(cur_cd, next_cd,
+			&xhci->cancel_cmd_list, cancel_cmd_list) {
+		if (cur_cd->cmd_trb == cmd_trb) {
+			if (cur_cd->command)
+				xhci_complete_cmd_in_cmd_wait_list(xhci,
+					cur_cd->command, COMP_CMD_STOP);
+			list_del(&cur_cd->cancel_cmd_list);
+			kfree(cur_cd);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the
+ * trb pointed by the command ring dequeue pointer is the trb we want to
+ * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will
+ * traverse the cancel_cmd_list to trun the all of the commands according
+ * to command descriptor to NO-OP trb.
+ */
+static int handle_stopped_cmd_ring(struct xhci_hcd *xhci,
+		int cmd_trb_comp_code)
+{
+	int cur_trb_is_good = 0;
+
+	/* Searching the cmd trb pointed by the command ring dequeue
+	 * pointer in command descriptor list. If it is found, free it.
+	 */
+	cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci,
+			xhci->cmd_ring->dequeue);
+
+	if (cmd_trb_comp_code == COMP_CMD_ABORT)
+		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+	else if (cmd_trb_comp_code == COMP_CMD_STOP) {
+		/* traversing the cancel_cmd_list and canceling
+		 * the command according to command descriptor
+		 */
+		xhci_cancel_cmd_in_cd_list(xhci);
+
+		xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+		/*
+		 * ring command ring doorbell again to restart the
+		 * command ring
+		 */
+		if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue)
+			xhci_ring_cmd_db(xhci);
+	}
+	return cur_trb_is_good;
+}
+
 static void handle_cmd_completion(struct xhci_hcd *xhci,
 		struct xhci_event_cmd *event)
 {
@@ -1111,6 +1365,22 @@
 		xhci->error_bitmask |= 1 << 5;
 		return;
 	}
+
+	if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) ||
+		(GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) {
+		/* If the return value is 0, we think the trb pointed by
+		 * command ring dequeue pointer is a good trb. The good
+		 * trb means we don't want to cancel the trb, but it have
+		 * been stopped by host. So we should handle it normally.
+		 * Otherwise, driver should invoke inc_deq() and return.
+		 */
+		if (handle_stopped_cmd_ring(xhci,
+				GET_COMP_CODE(le32_to_cpu(event->status)))) {
+			inc_deq(xhci, xhci->cmd_ring);
+			return;
+		}
+	}
+
 	switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
 		& TRB_TYPE_BITMASK) {
 	case TRB_TYPE(TRB_ENABLE_SLOT):
@@ -3400,7 +3670,9 @@
 			} else {
 				td->last_trb = ep_ring->enqueue;
 				field |= TRB_IOC;
-				if (xhci->hci_version == 0x100) {
+				if (xhci->hci_version == 0x100 &&
+						!(xhci->quirks &
+							XHCI_AVOID_BEI)) {
 					/* Set BEI bit except for the last td */
 					if (i < num_tds - 1)
 						field |= TRB_BEI;
diff -druN linux-libre-3.6-gnu/drivers/usb/otg/mxs-phy.c linux-libre-3.6.3-gnu/drivers/usb/otg/mxs-phy.c
--- linux-libre-3.6-gnu/drivers/usb/otg/mxs-phy.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/otg/mxs-phy.c	2012-10-21 12:32:56.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 #define DRIVER_NAME "mxs_phy"
 
@@ -34,9 +35,16 @@
 #define BM_USBPHY_CTRL_ENUTMILEVEL2		BIT(14)
 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
 
+/*
+ * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit
+ * so that connection and reset processing can be completed for the root hub.
+ */
+#define MXY_PHY_ENHOSTDISCONDETECT_DELAY	250
+
 struct mxs_phy {
 	struct usb_phy phy;
 	struct clk *clk;
+	struct delayed_work enhostdiscondetect_work;
 };
 
 #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
@@ -62,6 +70,7 @@
 
 	clk_prepare_enable(mxs_phy->clk);
 	mxs_phy_hw_init(mxs_phy);
+	INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);
 
 	return 0;
 }
@@ -76,13 +85,34 @@
 	clk_disable_unprepare(mxs_phy->clk);
 }
 
+static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws)
+{
+	struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy,
+						enhostdiscondetect_work.work);
+
+	/* Enable HOSTDISCONDETECT after delay. */
+	dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n");
+	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+				mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET);
+}
+
 static int mxs_phy_on_connect(struct usb_phy *phy, int port)
 {
+	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
 	dev_dbg(phy->dev, "Connect on port %d\n", port);
 
-	mxs_phy_hw_init(to_mxs_phy(phy));
-	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-			phy->io_priv + HW_USBPHY_CTRL_SET);
+	mxs_phy_hw_init(mxs_phy);
+
+	/*
+	 * Delay enabling ENHOSTDISCONDETECT so that connection and
+	 * reset processing can be completed for the root hub.
+	 */
+	dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n");
+	PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work,
+			mxs_phy_enhostdiscondetect_delay);
+	schedule_delayed_work(&mxs_phy->enhostdiscondetect_work,
+			msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY));
 
 	return 0;
 }
@@ -91,6 +121,8 @@
 {
 	dev_dbg(phy->dev, "Disconnect on port %d\n", port);
 
+	/* No need to delay before clearing ENHOSTDISCONDETECT. */
+	dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n");
 	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
 			phy->io_priv + HW_USBPHY_CTRL_CLR);
 
diff -druN linux-libre-3.6-gnu/drivers/usb/serial/ftdi_sio.c linux-libre-3.6.3-gnu/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.6-gnu/drivers/usb/serial/ftdi_sio.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/serial/ftdi_sio.c	2012-10-21 12:32:56.000000000 -0400
@@ -584,6 +584,8 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	/*
 	 * ELV devices:
 	 */
diff -druN linux-libre-3.6-gnu/drivers/usb/serial/ftdi_sio_ids.h linux-libre-3.6.3-gnu/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-3.6-gnu/drivers/usb/serial/ftdi_sio_ids.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/serial/ftdi_sio_ids.h	2012-10-21 12:32:56.000000000 -0400
@@ -517,6 +517,11 @@
  */
 #define FTDI_TAVIR_STK500_PID	0xFA33	/* STK500 AVR programmer */
 
+/*
+ * TIAO product ids (FTDI_VID)
+ * http://www.tiaowiki.com/w/Main_Page
+ */
+#define FTDI_TIAO_UMPA_PID	0x8a98	/* TIAO/DIYGADGET USB Multi-Protocol Adapter */
 
 
 /********************************/
diff -druN linux-libre-3.6-gnu/drivers/usb/serial/option.c linux-libre-3.6.3-gnu/drivers/usb/serial/option.c
--- linux-libre-3.6-gnu/drivers/usb/serial/option.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/serial/option.c	2012-10-21 12:32:56.000000000 -0400
@@ -870,7 +870,8 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
diff -druN linux-libre-3.6-gnu/drivers/usb/serial/qcaux.c linux-libre-3.6.3-gnu/drivers/usb/serial/qcaux.c
--- linux-libre-3.6-gnu/drivers/usb/serial/qcaux.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/serial/qcaux.c	2012-10-21 12:32:56.000000000 -0400
@@ -36,8 +36,6 @@
 #define UTSTARCOM_PRODUCT_UM175_V1		0x3712
 #define UTSTARCOM_PRODUCT_UM175_V2		0x3714
 #define UTSTARCOM_PRODUCT_UM175_ALLTEL		0x3715
-#define PANTECH_PRODUCT_UML190_VZW		0x3716
-#define PANTECH_PRODUCT_UML290_VZW		0x3718
 
 /* CMOTECH devices */
 #define CMOTECH_VENDOR_ID			0x16d8
@@ -68,11 +66,9 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) },  /* NMEA */
-	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) },  /* WMC */
-	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },  /* DIAG */
+	{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) },  /* NMEA */
+	{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) },  /* WMC */
+	{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) },  /* DIAG */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff -druN linux-libre-3.6-gnu/drivers/usb/serial/usb-serial.c linux-libre-3.6.3-gnu/drivers/usb/serial/usb-serial.c
--- linux-libre-3.6-gnu/drivers/usb/serial/usb-serial.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/usb/serial/usb-serial.c	2012-10-21 12:32:56.000000000 -0400
@@ -1426,9 +1426,10 @@
 
 	/* we only set the reset_resume field if the serial_driver has one */
 	for (sd = serial_drivers; *sd; ++sd) {
-		if ((*sd)->reset_resume)
+		if ((*sd)->reset_resume) {
 			udriver->reset_resume = usb_serial_reset_resume;
 			break;
+		}
 	}
 
 	rc = usb_register(udriver);
diff -druN linux-libre-3.6-gnu/drivers/vfio/pci/vfio_pci_intrs.c linux-libre-3.6.3-gnu/drivers/vfio/pci/vfio_pci_intrs.c
--- linux-libre-3.6-gnu/drivers/vfio/pci/vfio_pci_intrs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/vfio/pci/vfio_pci_intrs.c	2012-10-21 12:32:56.000000000 -0400
@@ -366,6 +366,17 @@
 		return -ENOMEM;
 
 	vdev->num_ctx = 1;
+
+	/*
+	 * If the virtual interrupt is masked, restore it.  Devices
+	 * supporting DisINTx can be masked at the hardware level
+	 * here, non-PCI-2.3 devices will have to wait until the
+	 * interrupt is enabled.
+	 */
+	vdev->ctx[0].masked = vdev->virq_disabled;
+	if (vdev->pci_2_3)
+		pci_intx(vdev->pdev, !vdev->ctx[0].masked);
+
 	vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX;
 
 	return 0;
@@ -400,25 +411,26 @@
 		return PTR_ERR(trigger);
 	}
 
+	vdev->ctx[0].trigger = trigger;
+
 	if (!vdev->pci_2_3)
 		irqflags = 0;
 
 	ret = request_irq(pdev->irq, vfio_intx_handler,
 			  irqflags, vdev->ctx[0].name, vdev);
 	if (ret) {
+		vdev->ctx[0].trigger = NULL;
 		kfree(vdev->ctx[0].name);
 		eventfd_ctx_put(trigger);
 		return ret;
 	}
 
-	vdev->ctx[0].trigger = trigger;
-
 	/*
 	 * INTx disable will stick across the new irq setup,
 	 * disable_irq won't.
 	 */
 	spin_lock_irqsave(&vdev->irqlock, flags);
-	if (!vdev->pci_2_3 && (vdev->ctx[0].masked || vdev->virq_disabled))
+	if (!vdev->pci_2_3 && vdev->ctx[0].masked)
 		disable_irq_nosync(pdev->irq);
 	spin_unlock_irqrestore(&vdev->irqlock, flags);
 
diff -druN linux-libre-3.6-gnu/drivers/video/udlfb.c linux-libre-3.6.3-gnu/drivers/video/udlfb.c
--- linux-libre-3.6-gnu/drivers/video/udlfb.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/video/udlfb.c	2012-10-21 12:32:56.000000000 -0400
@@ -647,7 +647,7 @@
 	result = fb_sys_write(info, buf, count, ppos);
 
 	if (result > 0) {
-		int start = max((int)(offset / info->fix.line_length) - 1, 0);
+		int start = max((int)(offset / info->fix.line_length), 0);
 		int lines = min((u32)((result / info->fix.line_length) + 1),
 				(u32)info->var.yres);
 
diff -druN linux-libre-3.6-gnu/drivers/video/via/via_clock.c linux-libre-3.6.3-gnu/drivers/video/via/via_clock.c
--- linux-libre-3.6-gnu/drivers/video/via/via_clock.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/video/via/via_clock.c	2012-10-21 12:32:56.000000000 -0400
@@ -25,6 +25,7 @@
 
 #include <linux/kernel.h>
 #include <linux/via-core.h>
+#include <asm/olpc.h>
 #include "via_clock.h"
 #include "global.h"
 #include "debug.h"
@@ -289,6 +290,10 @@
 	printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
 }
 
+static void noop_set_clock_state(u8 state)
+{
+}
+
 void via_clock_init(struct via_clock *clock, int gfx_chip)
 {
 	switch (gfx_chip) {
@@ -346,4 +351,18 @@
 		break;
 
 	}
+
+	if (machine_is_olpc()) {
+		/* The OLPC XO-1.5 cannot suspend/resume reliably if the
+		 * IGA1/IGA2 clocks are set as on or off (memory rot
+		 * occasionally happens during suspend under such
+		 * configurations).
+		 *
+		 * The only known stable scenario is to leave this bits as-is,
+		 * which in their default states are documented to enable the
+		 * clock only when it is needed.
+		 */
+		clock->set_primary_clock_state = noop_set_clock_state;
+		clock->set_secondary_clock_state = noop_set_clock_state;
+	}
 }
diff -druN linux-libre-3.6-gnu/drivers/xen/xenbus/xenbus_xs.c linux-libre-3.6.3-gnu/drivers/xen/xenbus/xenbus_xs.c
--- linux-libre-3.6-gnu/drivers/xen/xenbus/xenbus_xs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/xen/xenbus/xenbus_xs.c	2012-10-21 12:32:56.000000000 -0400
@@ -47,6 +47,7 @@
 #include <xen/xenbus.h>
 #include <xen/xen.h>
 #include "xenbus_comms.h"
+#include <asm/xen/hypervisor.h>
 
 struct xs_stored_msg {
 	struct list_head list;
@@ -617,7 +618,24 @@
 
 	return NULL;
 }
+/*
+ * Certain older XenBus toolstack cannot handle reading values that are
+ * not populated. Some Xen 3.4 installation are incapable of doing this
+ * so if we are running on anything older than 4 do not attempt to read
+ * control/platform-feature-xs_reset_watches.
+ */
+static bool xen_strict_xenbus_quirk()
+{
+	uint32_t eax, ebx, ecx, edx, base;
 
+	base = xen_cpuid_base();
+	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
+
+	if ((eax >> 16) < 4)
+		return true;
+	return false;
+
+}
 static void xs_reset_watches(void)
 {
 	int err, supported = 0;
@@ -625,6 +643,9 @@
 	if (!xen_hvm_domain())
 		return;
 
+	if (xen_strict_xenbus_quirk())
+		return;
+
 	err = xenbus_scanf(XBT_NIL, "control",
 			"platform-feature-xs_reset_watches", "%d", &supported);
 	if (err != 1 || !supported)
diff -druN linux-libre-3.6-gnu/drivers/xen/xen-pciback/pci_stub.c linux-libre-3.6.3-gnu/drivers/xen/xen-pciback/pci_stub.c
--- linux-libre-3.6-gnu/drivers/xen/xen-pciback/pci_stub.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/drivers/xen/xen-pciback/pci_stub.c	2012-10-21 12:32:56.000000000 -0400
@@ -362,6 +362,7 @@
 	else {
 		dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
 		__pci_reset_function_locked(dev);
+		pci_restore_state(dev);
 	}
 	/* Now disable the device (this also ensures some private device
 	 * data is setup before we export)
diff -druN linux-libre-3.6-gnu/fs/autofs4/root.c linux-libre-3.6.3-gnu/fs/autofs4/root.c
--- linux-libre-3.6-gnu/fs/autofs4/root.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/autofs4/root.c	2012-10-21 12:32:56.000000000 -0400
@@ -392,10 +392,12 @@
 		ino->flags |= AUTOFS_INF_PENDING;
 		spin_unlock(&sbi->fs_lock);
 		status = autofs4_mount_wait(dentry);
-		if (status)
-			return ERR_PTR(status);
 		spin_lock(&sbi->fs_lock);
 		ino->flags &= ~AUTOFS_INF_PENDING;
+		if (status) {
+			spin_unlock(&sbi->fs_lock);
+			return ERR_PTR(status);
+		}
 	}
 done:
 	if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
diff -druN linux-libre-3.6-gnu/fs/binfmt_elf.c linux-libre-3.6.3-gnu/fs/binfmt_elf.c
--- linux-libre-3.6-gnu/fs/binfmt_elf.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/binfmt_elf.c	2012-10-21 12:32:56.000000000 -0400
@@ -1696,30 +1696,19 @@
 		return 0;
 	info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
 	if (!info->psinfo)
-		goto notes_free;
+		return 0;
 	info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL);
 	if (!info->prstatus)
-		goto psinfo_free;
+		return 0;
 	info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL);
 	if (!info->fpu)
-		goto prstatus_free;
+		return 0;
 #ifdef ELF_CORE_COPY_XFPREGS
 	info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL);
 	if (!info->xfpu)
-		goto fpu_free;
+		return 0;
 #endif
 	return 1;
-#ifdef ELF_CORE_COPY_XFPREGS
- fpu_free:
-	kfree(info->fpu);
-#endif
- prstatus_free:
-	kfree(info->prstatus);
- psinfo_free:
-	kfree(info->psinfo);
- notes_free:
-	kfree(info->notes);
-	return 0;
 }
 
 static int fill_note_info(struct elfhdr *elf, int phdrs,
diff -druN linux-libre-3.6-gnu/fs/buffer.c linux-libre-3.6.3-gnu/fs/buffer.c
--- linux-libre-3.6-gnu/fs/buffer.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/buffer.c	2012-10-21 12:32:56.000000000 -0400
@@ -2312,12 +2312,6 @@
 	loff_t size;
 	int ret;
 
-	/*
-	 * Update file times before taking page lock. We may end up failing the
-	 * fault so this update may be superfluous but who really cares...
-	 */
-	file_update_time(vma->vm_file);
-
 	lock_page(page);
 	size = i_size_read(inode);
 	if ((page->mapping != inode->i_mapping) ||
@@ -2355,6 +2349,13 @@
 	struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb;
 
 	sb_start_pagefault(sb);
+
+	/*
+	 * Update file times before taking page lock. We may end up failing the
+	 * fault so this update may be superfluous but who really cares...
+	 */
+	file_update_time(vma->vm_file);
+
 	ret = __block_page_mkwrite(vma, vmf, get_block);
 	sb_end_pagefault(sb);
 	return block_page_mkwrite_return(ret);
diff -druN linux-libre-3.6-gnu/fs/ceph/export.c linux-libre-3.6.3-gnu/fs/ceph/export.c
--- linux-libre-3.6-gnu/fs/ceph/export.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/ceph/export.c	2012-10-21 12:32:56.000000000 -0400
@@ -99,7 +99,7 @@
  * FIXME: we should try harder by querying the mds for the ino.
  */
 static struct dentry *__fh_to_dentry(struct super_block *sb,
-				     struct ceph_nfs_fh *fh)
+				     struct ceph_nfs_fh *fh, int fh_len)
 {
 	struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
 	struct inode *inode;
@@ -107,6 +107,9 @@
 	struct ceph_vino vino;
 	int err;
 
+	if (fh_len < sizeof(*fh) / 4)
+		return ERR_PTR(-ESTALE);
+
 	dout("__fh_to_dentry %llx\n", fh->ino);
 	vino.ino = fh->ino;
 	vino.snap = CEPH_NOSNAP;
@@ -150,7 +153,7 @@
  * convert connectable fh to dentry
  */
 static struct dentry *__cfh_to_dentry(struct super_block *sb,
-				      struct ceph_nfs_confh *cfh)
+				      struct ceph_nfs_confh *cfh, int fh_len)
 {
 	struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
 	struct inode *inode;
@@ -158,6 +161,9 @@
 	struct ceph_vino vino;
 	int err;
 
+	if (fh_len < sizeof(*cfh) / 4)
+		return ERR_PTR(-ESTALE);
+
 	dout("__cfh_to_dentry %llx (%llx/%x)\n",
 	     cfh->ino, cfh->parent_ino, cfh->parent_name_hash);
 
@@ -207,9 +213,11 @@
 					int fh_len, int fh_type)
 {
 	if (fh_type == 1)
-		return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw);
+		return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw,
+								fh_len);
 	else
-		return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw);
+		return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw,
+								fh_len);
 }
 
 /*
@@ -230,6 +238,8 @@
 
 	if (fh_type == 1)
 		return ERR_PTR(-ESTALE);
+	if (fh_len < sizeof(*cfh) / 4)
+		return ERR_PTR(-ESTALE);
 
 	pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino,
 		 cfh->parent_name_hash);
diff -druN linux-libre-3.6-gnu/fs/cifs/cifs_unicode.c linux-libre-3.6.3-gnu/fs/cifs/cifs_unicode.c
--- linux-libre-3.6-gnu/fs/cifs/cifs_unicode.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/cifs/cifs_unicode.c	2012-10-21 12:32:56.000000000 -0400
@@ -203,6 +203,27 @@
 	int i;
 	wchar_t wchar_to; /* needed to quiet sparse */
 
+	/* special case for utf8 to handle no plane0 chars */
+	if (!strcmp(codepage->charset, "utf8")) {
+		/*
+		 * convert utf8 -> utf16, we assume we have enough space
+		 * as caller should have assumed conversion does not overflow
+		 * in destination len is length in wchar_t units (16bits)
+		 */
+		i  = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
+				       (wchar_t *) to, len);
+
+		/* if success terminate and exit */
+		if (i >= 0)
+			goto success;
+		/*
+		 * if fails fall back to UCS encoding as this
+		 * function should not return negative values
+		 * currently can fail only if source contains
+		 * invalid encoded characters
+		 */
+	}
+
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 		charlen = codepage->char2uni(from, len, &wchar_to);
 		if (charlen < 1) {
@@ -215,6 +236,7 @@
 		put_unaligned_le16(wchar_to, &to[i]);
 	}
 
+success:
 	put_unaligned_le16(0, &to[i]);
 	return i;
 }
diff -druN linux-libre-3.6-gnu/fs/cifs/connect.c linux-libre-3.6.3-gnu/fs/cifs/connect.c
--- linux-libre-3.6-gnu/fs/cifs/connect.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/cifs/connect.c	2012-10-21 12:32:56.000000000 -0400
@@ -67,6 +67,7 @@
 	/* Mount options that take no arguments */
 	Opt_user_xattr, Opt_nouser_xattr,
 	Opt_forceuid, Opt_noforceuid,
+	Opt_forcegid, Opt_noforcegid,
 	Opt_noblocksend, Opt_noautotune,
 	Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
 	Opt_mapchars, Opt_nomapchars, Opt_sfu,
@@ -118,6 +119,8 @@
 	{ Opt_nouser_xattr, "nouser_xattr" },
 	{ Opt_forceuid, "forceuid" },
 	{ Opt_noforceuid, "noforceuid" },
+	{ Opt_forcegid, "forcegid" },
+	{ Opt_noforcegid, "noforcegid" },
 	{ Opt_noblocksend, "noblocksend" },
 	{ Opt_noautotune, "noautotune" },
 	{ Opt_hard, "hard" },
@@ -1190,6 +1193,12 @@
 		case Opt_noforceuid:
 			override_uid = 0;
 			break;
+		case Opt_forcegid:
+			override_gid = 1;
+			break;
+		case Opt_noforcegid:
+			override_gid = 0;
+			break;
 		case Opt_noblocksend:
 			vol->noblocksnd = 1;
 			break;
diff -druN linux-libre-3.6-gnu/fs/ext4/inode.c linux-libre-3.6.3-gnu/fs/ext4/inode.c
--- linux-libre-3.6-gnu/fs/ext4/inode.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/ext4/inode.c	2012-10-21 12:32:56.000000000 -0400
@@ -2463,6 +2463,16 @@
 	free_blocks  = EXT4_C2B(sbi,
 		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
 	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter);
+	/*
+	 * Start pushing delalloc when 1/2 of free blocks are dirty.
+	 */
+	if (dirty_blocks && (free_blocks < 2 * dirty_blocks) &&
+	    !writeback_in_progress(sb->s_bdi) &&
+	    down_read_trylock(&sb->s_umount)) {
+		writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE);
+		up_read(&sb->s_umount);
+	}
+
 	if (2 * free_blocks < 3 * dirty_blocks ||
 		free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) {
 		/*
@@ -2471,13 +2481,6 @@
 		 */
 		return 1;
 	}
-	/*
-	 * Even if we don't switch but are nearing capacity,
-	 * start pushing delalloc when 1/2 of free blocks are dirty.
-	 */
-	if (free_blocks < 2 * dirty_blocks)
-		writeback_inodes_sb_if_idle(sb, WB_REASON_FS_FREE_SPACE);
-
 	return 0;
 }
 
@@ -4052,6 +4055,7 @@
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	struct buffer_head *bh = iloc->bh;
 	int err = 0, rc, block;
+	int need_datasync = 0;
 	uid_t i_uid;
 	gid_t i_gid;
 
@@ -4102,7 +4106,10 @@
 		raw_inode->i_file_acl_high =
 			cpu_to_le16(ei->i_file_acl >> 32);
 	raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl);
-	ext4_isize_set(raw_inode, ei->i_disksize);
+	if (ei->i_disksize != ext4_isize(raw_inode)) {
+		ext4_isize_set(raw_inode, ei->i_disksize);
+		need_datasync = 1;
+	}
 	if (ei->i_disksize > 0x7fffffffULL) {
 		struct super_block *sb = inode->i_sb;
 		if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -4155,7 +4162,7 @@
 		err = rc;
 	ext4_clear_inode_state(inode, EXT4_STATE_NEW);
 
-	ext4_update_inode_fsync_trans(handle, inode, 0);
+	ext4_update_inode_fsync_trans(handle, inode, need_datasync);
 out_brelse:
 	brelse(bh);
 	ext4_std_error(inode->i_sb, err);
@@ -4780,6 +4787,7 @@
 	int retries = 0;
 
 	sb_start_pagefault(inode->i_sb);
+	file_update_time(vma->vm_file);
 	/* Delalloc case is easy... */
 	if (test_opt(inode->i_sb, DELALLOC) &&
 	    !ext4_should_journal_data(inode) &&
diff -druN linux-libre-3.6-gnu/fs/ext4/move_extent.c linux-libre-3.6.3-gnu/fs/ext4/move_extent.c
--- linux-libre-3.6-gnu/fs/ext4/move_extent.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/ext4/move_extent.c	2012-10-21 12:32:56.000000000 -0400
@@ -141,55 +141,21 @@
 }
 
 /**
- * mext_check_null_inode - NULL check for two inodes
- *
- * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0.
- */
-static int
-mext_check_null_inode(struct inode *inode1, struct inode *inode2,
-		      const char *function, unsigned int line)
-{
-	int ret = 0;
-
-	if (inode1 == NULL) {
-		__ext4_error(inode2->i_sb, function, line,
-			"Both inodes should not be NULL: "
-			"inode1 NULL inode2 %lu", inode2->i_ino);
-		ret = -EIO;
-	} else if (inode2 == NULL) {
-		__ext4_error(inode1->i_sb, function, line,
-			"Both inodes should not be NULL: "
-			"inode1 %lu inode2 NULL", inode1->i_ino);
-		ret = -EIO;
-	}
-	return ret;
-}
-
-/**
  * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem
  *
- * @orig_inode:		original inode structure
- * @donor_inode:	donor inode structure
- * Acquire write lock of i_data_sem of the two inodes (orig and donor) by
- * i_ino order.
+ * Acquire write lock of i_data_sem of the two inodes
  */
 static void
-double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode)
+double_down_write_data_sem(struct inode *first, struct inode *second)
 {
-	struct inode *first = orig_inode, *second = donor_inode;
+	if (first < second) {
+		down_write(&EXT4_I(first)->i_data_sem);
+		down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING);
+	} else {
+		down_write(&EXT4_I(second)->i_data_sem);
+		down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING);
 
-	/*
-	 * Use the inode number to provide the stable locking order instead
-	 * of its address, because the C language doesn't guarantee you can
-	 * compare pointers that don't come from the same array.
-	 */
-	if (donor_inode->i_ino < orig_inode->i_ino) {
-		first = donor_inode;
-		second = orig_inode;
 	}
-
-	down_write(&EXT4_I(first)->i_data_sem);
-	down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING);
 }
 
 /**
@@ -969,14 +935,6 @@
 		return -EINVAL;
 	}
 
-	/* Files should be in the same ext4 FS */
-	if (orig_inode->i_sb != donor_inode->i_sb) {
-		ext4_debug("ext4 move extent: The argument files "
-			"should be in same FS [ino:orig %lu, donor %lu]\n",
-			orig_inode->i_ino, donor_inode->i_ino);
-		return -EINVAL;
-	}
-
 	/* Ext4 move extent supports only extent based file */
 	if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) {
 		ext4_debug("ext4 move extent: orig file is not extents "
@@ -1072,35 +1030,19 @@
  * @inode1:	the inode structure
  * @inode2:	the inode structure
  *
- * Lock two inodes' i_mutex by i_ino order.
- * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0.
+ * Lock two inodes' i_mutex
  */
-static int
+static void
 mext_inode_double_lock(struct inode *inode1, struct inode *inode2)
 {
-	int ret = 0;
-
-	BUG_ON(inode1 == NULL && inode2 == NULL);
-
-	ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__);
-	if (ret < 0)
-		goto out;
-
-	if (inode1 == inode2) {
-		mutex_lock(&inode1->i_mutex);
-		goto out;
-	}
-
-	if (inode1->i_ino < inode2->i_ino) {
+	BUG_ON(inode1 == inode2);
+	if (inode1 < inode2) {
 		mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
 		mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
 	} else {
 		mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT);
 		mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD);
 	}
-
-out:
-	return ret;
 }
 
 /**
@@ -1109,28 +1051,13 @@
  * @inode1:     the inode that is released first
  * @inode2:     the inode that is released second
  *
- * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0.
  */
 
-static int
+static void
 mext_inode_double_unlock(struct inode *inode1, struct inode *inode2)
 {
-	int ret = 0;
-
-	BUG_ON(inode1 == NULL && inode2 == NULL);
-
-	ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__);
-	if (ret < 0)
-		goto out;
-
-	if (inode1)
-		mutex_unlock(&inode1->i_mutex);
-
-	if (inode2 && inode2 != inode1)
-		mutex_unlock(&inode2->i_mutex);
-
-out:
-	return ret;
+	mutex_unlock(&inode1->i_mutex);
+	mutex_unlock(&inode2->i_mutex);
 }
 
 /**
@@ -1187,16 +1114,23 @@
 	ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks = 0;
 	ext4_lblk_t rest_blocks;
 	pgoff_t orig_page_offset = 0, seq_end_page;
-	int ret1, ret2, depth, last_extent = 0;
+	int ret, depth, last_extent = 0;
 	int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
 	int data_offset_in_page;
 	int block_len_in_page;
 	int uninit;
 
-	/* orig and donor should be different file */
-	if (orig_inode->i_ino == donor_inode->i_ino) {
+	if (orig_inode->i_sb != donor_inode->i_sb) {
+		ext4_debug("ext4 move extent: The argument files "
+			"should be in same FS [ino:orig %lu, donor %lu]\n",
+			orig_inode->i_ino, donor_inode->i_ino);
+		return -EINVAL;
+	}
+
+	/* orig and donor should be different inodes */
+	if (orig_inode == donor_inode) {
 		ext4_debug("ext4 move extent: The argument files should not "
-			"be same file [ino:orig %lu, donor %lu]\n",
+			"be same inode [ino:orig %lu, donor %lu]\n",
 			orig_inode->i_ino, donor_inode->i_ino);
 		return -EINVAL;
 	}
@@ -1208,18 +1142,21 @@
 			orig_inode->i_ino, donor_inode->i_ino);
 		return -EINVAL;
 	}
-
+	/* TODO: This is non obvious task to swap blocks for inodes with full
+	   jornaling enabled */
+	if (ext4_should_journal_data(orig_inode) ||
+	    ext4_should_journal_data(donor_inode)) {
+		return -EINVAL;
+	}
 	/* Protect orig and donor inodes against a truncate */
-	ret1 = mext_inode_double_lock(orig_inode, donor_inode);
-	if (ret1 < 0)
-		return ret1;
+	mext_inode_double_lock(orig_inode, donor_inode);
 
 	/* Protect extent tree against block allocations via delalloc */
 	double_down_write_data_sem(orig_inode, donor_inode);
 	/* Check the filesystem environment whether move_extent can be done */
-	ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start,
+	ret = mext_check_arguments(orig_inode, donor_inode, orig_start,
 				    donor_start, &len);
-	if (ret1)
+	if (ret)
 		goto out;
 
 	file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits;
@@ -1227,13 +1164,13 @@
 	if (file_end < block_end)
 		len -= block_end - file_end;
 
-	ret1 = get_ext_path(orig_inode, block_start, &orig_path);
-	if (ret1)
+	ret = get_ext_path(orig_inode, block_start, &orig_path);
+	if (ret)
 		goto out;
 
 	/* Get path structure to check the hole */
-	ret1 = get_ext_path(orig_inode, block_start, &holecheck_path);
-	if (ret1)
+	ret = get_ext_path(orig_inode, block_start, &holecheck_path);
+	if (ret)
 		goto out;
 
 	depth = ext_depth(orig_inode);
@@ -1252,13 +1189,13 @@
 		last_extent = mext_next_extent(orig_inode,
 					holecheck_path, &ext_cur);
 		if (last_extent < 0) {
-			ret1 = last_extent;
+			ret = last_extent;
 			goto out;
 		}
 		last_extent = mext_next_extent(orig_inode, orig_path,
 							&ext_dummy);
 		if (last_extent < 0) {
-			ret1 = last_extent;
+			ret = last_extent;
 			goto out;
 		}
 		seq_start = le32_to_cpu(ext_cur->ee_block);
@@ -1272,7 +1209,7 @@
 	if (le32_to_cpu(ext_cur->ee_block) > block_end) {
 		ext4_debug("ext4 move extent: The specified range of file "
 							"may be the hole\n");
-		ret1 = -EINVAL;
+		ret = -EINVAL;
 		goto out;
 	}
 
@@ -1292,7 +1229,7 @@
 		last_extent = mext_next_extent(orig_inode, holecheck_path,
 						&ext_cur);
 		if (last_extent < 0) {
-			ret1 = last_extent;
+			ret = last_extent;
 			break;
 		}
 		add_blocks = ext4_ext_get_actual_len(ext_cur);
@@ -1349,18 +1286,18 @@
 						orig_page_offset,
 						data_offset_in_page,
 						block_len_in_page, uninit,
-						&ret1);
+						&ret);
 
 			/* Count how many blocks we have exchanged */
 			*moved_len += block_len_in_page;
-			if (ret1 < 0)
+			if (ret < 0)
 				break;
 			if (*moved_len > len) {
 				EXT4_ERROR_INODE(orig_inode,
 					"We replaced blocks too much! "
 					"sum of replaced: %llu requested: %llu",
 					*moved_len, len);
-				ret1 = -EIO;
+				ret = -EIO;
 				break;
 			}
 
@@ -1374,22 +1311,22 @@
 		}
 
 		double_down_write_data_sem(orig_inode, donor_inode);
-		if (ret1 < 0)
+		if (ret < 0)
 			break;
 
 		/* Decrease buffer counter */
 		if (holecheck_path)
 			ext4_ext_drop_refs(holecheck_path);
-		ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path);
-		if (ret1)
+		ret = get_ext_path(orig_inode, seq_start, &holecheck_path);
+		if (ret)
 			break;
 		depth = holecheck_path->p_depth;
 
 		/* Decrease buffer counter */
 		if (orig_path)
 			ext4_ext_drop_refs(orig_path);
-		ret1 = get_ext_path(orig_inode, seq_start, &orig_path);
-		if (ret1)
+		ret = get_ext_path(orig_inode, seq_start, &orig_path);
+		if (ret)
 			break;
 
 		ext_cur = holecheck_path[depth].p_ext;
@@ -1412,12 +1349,7 @@
 		kfree(holecheck_path);
 	}
 	double_up_write_data_sem(orig_inode, donor_inode);
-	ret2 = mext_inode_double_unlock(orig_inode, donor_inode);
-
-	if (ret1)
-		return ret1;
-	else if (ret2)
-		return ret2;
+	mext_inode_double_unlock(orig_inode, donor_inode);
 
-	return 0;
+	return ret;
 }
diff -druN linux-libre-3.6-gnu/fs/ext4/namei.c linux-libre-3.6.3-gnu/fs/ext4/namei.c
--- linux-libre-3.6-gnu/fs/ext4/namei.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/ext4/namei.c	2012-10-21 12:32:56.000000000 -0400
@@ -2149,9 +2149,7 @@
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
-#ifdef CONFIG_EXT4_FS_XATTR
 		inode->i_op = &ext4_special_inode_operations;
-#endif
 		err = ext4_add_nondir(handle, dentry, inode);
 	}
 	ext4_journal_stop(handle);
diff -druN linux-libre-3.6-gnu/fs/ext4/resize.c linux-libre-3.6.3-gnu/fs/ext4/resize.c
--- linux-libre-3.6-gnu/fs/ext4/resize.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/ext4/resize.c	2012-10-21 12:32:56.000000000 -0400
@@ -200,8 +200,11 @@
  * be a partial of a flex group.
  *
  * @sb: super block of fs to which the groups belongs
+ *
+ * Returns 0 on a successful allocation of the metadata blocks in the
+ * block group.
  */
-static void ext4_alloc_group_tables(struct super_block *sb,
+static int ext4_alloc_group_tables(struct super_block *sb,
 				struct ext4_new_flex_group_data *flex_gd,
 				int flexbg_size)
 {
@@ -226,6 +229,8 @@
 	       (last_group & ~(flexbg_size - 1))));
 next_group:
 	group = group_data[0].group;
+	if (src_group >= group_data[0].group + flex_gd->count)
+		return -ENOSPC;
 	start_blk = ext4_group_first_block_no(sb, src_group);
 	last_blk = start_blk + group_data[src_group - group].blocks_count;
 
@@ -235,7 +240,6 @@
 
 	start_blk += overhead;
 
-	BUG_ON(src_group >= group_data[0].group + flex_gd->count);
 	/* We collect contiguous blocks as much as possible. */
 	src_group++;
 	for (; src_group <= last_group; src_group++)
@@ -300,6 +304,7 @@
 			       group_data[i].free_blocks_count);
 		}
 	}
+	return 0;
 }
 
 static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
@@ -451,6 +456,9 @@
 		gdblocks = ext4_bg_num_gdb(sb, group);
 		start = ext4_group_first_block_no(sb, group);
 
+		if (!ext4_bg_has_super(sb, group))
+			goto handle_itb;
+
 		/* Copy all of the GDT blocks into the backup in this group */
 		for (j = 0, block = start + 1; j < gdblocks; j++, block++) {
 			struct buffer_head *gdb;
@@ -493,6 +501,7 @@
 				goto out;
 		}
 
+handle_itb:
 		/* Initialize group tables of the grop @group */
 		if (!(bg_flags[i] & EXT4_BG_INODE_ZEROED))
 			goto handle_bb;
@@ -1349,13 +1358,15 @@
 		err = err2;
 
 	if (!err) {
-		int i;
+		int gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
+		int gdb_num_end = ((group + flex_gd->count - 1) /
+				   EXT4_DESC_PER_BLOCK(sb));
+
 		update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
 			       sizeof(struct ext4_super_block));
-		for (i = 0; i < flex_gd->count; i++, group++) {
+		for (; gdb_num <= gdb_num_end; gdb_num++) {
 			struct buffer_head *gdb_bh;
-			int gdb_num;
-			gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb);
+
 			gdb_bh = sbi->s_group_desc[gdb_num];
 			update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
 				       gdb_bh->b_size);
@@ -1729,7 +1740,8 @@
 	 */
 	while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count,
 					      flexbg_size)) {
-		ext4_alloc_group_tables(sb, flex_gd, flexbg_size);
+		if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0)
+			break;
 		err = ext4_flex_group_add(sb, resize_inode, flex_gd);
 		if (unlikely(err))
 			break;
diff -druN linux-libre-3.6-gnu/fs/ext4/super.c linux-libre-3.6.3-gnu/fs/ext4/super.c
--- linux-libre-3.6-gnu/fs/ext4/super.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/ext4/super.c	2012-10-21 12:32:56.000000000 -0400
@@ -1735,7 +1735,7 @@
 
 static const char *token2str(int token)
 {
-	static const struct match_token *t;
+	const struct match_token *t;
 
 	for (t = tokens; t->token != Opt_err; t++)
 		if (t->token == token && !strchr(t->pattern, '='))
diff -druN linux-libre-3.6-gnu/fs/fs-writeback.c linux-libre-3.6.3-gnu/fs/fs-writeback.c
--- linux-libre-3.6-gnu/fs/fs-writeback.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/fs-writeback.c	2012-10-21 12:32:56.000000000 -0400
@@ -63,6 +63,7 @@
 {
 	return test_bit(BDI_writeback_running, &bdi->state);
 }
+EXPORT_SYMBOL(writeback_in_progress);
 
 static inline struct backing_dev_info *inode_to_bdi(struct inode *inode)
 {
diff -druN linux-libre-3.6-gnu/fs/gfs2/export.c linux-libre-3.6.3-gnu/fs/gfs2/export.c
--- linux-libre-3.6-gnu/fs/gfs2/export.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/gfs2/export.c	2012-10-21 12:32:56.000000000 -0400
@@ -161,6 +161,8 @@
 	case GFS2_SMALL_FH_SIZE:
 	case GFS2_LARGE_FH_SIZE:
 	case GFS2_OLD_FH_SIZE:
+		if (fh_len < GFS2_SMALL_FH_SIZE)
+			return NULL;
 		this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
 		this.no_formal_ino |= be32_to_cpu(fh[1]);
 		this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
@@ -180,6 +182,8 @@
 	switch (fh_type) {
 	case GFS2_LARGE_FH_SIZE:
 	case GFS2_OLD_FH_SIZE:
+		if (fh_len < GFS2_LARGE_FH_SIZE)
+			return NULL;
 		parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
 		parent.no_formal_ino |= be32_to_cpu(fh[5]);
 		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
diff -druN linux-libre-3.6-gnu/fs/isofs/export.c linux-libre-3.6.3-gnu/fs/isofs/export.c
--- linux-libre-3.6-gnu/fs/isofs/export.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/isofs/export.c	2012-10-21 12:32:56.000000000 -0400
@@ -175,7 +175,7 @@
 {
 	struct isofs_fid *ifid = (struct isofs_fid *)fid;
 
-	if (fh_type != 2)
+	if (fh_len < 2 || fh_type != 2)
 		return NULL;
 
 	return isofs_export_iget(sb,
diff -druN linux-libre-3.6-gnu/fs/jbd/commit.c linux-libre-3.6.3-gnu/fs/jbd/commit.c
--- linux-libre-3.6-gnu/fs/jbd/commit.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/jbd/commit.c	2012-10-21 12:32:56.000000000 -0400
@@ -86,7 +86,12 @@
 static void release_data_buffer(struct buffer_head *bh)
 {
 	if (buffer_freed(bh)) {
+		WARN_ON_ONCE(buffer_dirty(bh));
 		clear_buffer_freed(bh);
+		clear_buffer_mapped(bh);
+		clear_buffer_new(bh);
+		clear_buffer_req(bh);
+		bh->b_bdev = NULL;
 		release_buffer_page(bh);
 	} else
 		put_bh(bh);
@@ -866,17 +871,35 @@
 		 * there's no point in keeping a checkpoint record for
 		 * it. */
 
-		/* A buffer which has been freed while still being
-		 * journaled by a previous transaction may end up still
-		 * being dirty here, but we want to avoid writing back
-		 * that buffer in the future after the "add to orphan"
-		 * operation been committed,  That's not only a performance
-		 * gain, it also stops aliasing problems if the buffer is
-		 * left behind for writeback and gets reallocated for another
-		 * use in a different page. */
-		if (buffer_freed(bh) && !jh->b_next_transaction) {
-			clear_buffer_freed(bh);
-			clear_buffer_jbddirty(bh);
+		/*
+		 * A buffer which has been freed while still being journaled by
+		 * a previous transaction.
+		 */
+		if (buffer_freed(bh)) {
+			/*
+			 * If the running transaction is the one containing
+			 * "add to orphan" operation (b_next_transaction !=
+			 * NULL), we have to wait for that transaction to
+			 * commit before we can really get rid of the buffer.
+			 * So just clear b_modified to not confuse transaction
+			 * credit accounting and refile the buffer to
+			 * BJ_Forget of the running transaction. If the just
+			 * committed transaction contains "add to orphan"
+			 * operation, we can completely invalidate the buffer
+			 * now. We are rather throughout in that since the
+			 * buffer may be still accessible when blocksize <
+			 * pagesize and it is attached to the last partial
+			 * page.
+			 */
+			jh->b_modified = 0;
+			if (!jh->b_next_transaction) {
+				clear_buffer_freed(bh);
+				clear_buffer_jbddirty(bh);
+				clear_buffer_mapped(bh);
+				clear_buffer_new(bh);
+				clear_buffer_req(bh);
+				bh->b_bdev = NULL;
+			}
 		}
 
 		if (buffer_jbddirty(bh)) {
diff -druN linux-libre-3.6-gnu/fs/jbd/transaction.c linux-libre-3.6.3-gnu/fs/jbd/transaction.c
--- linux-libre-3.6-gnu/fs/jbd/transaction.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/jbd/transaction.c	2012-10-21 12:32:56.000000000 -0400
@@ -1843,15 +1843,16 @@
  * We're outside-transaction here.  Either or both of j_running_transaction
  * and j_committing_transaction may be NULL.
  */
-static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
+				int partial_page)
 {
 	transaction_t *transaction;
 	struct journal_head *jh;
 	int may_free = 1;
-	int ret;
 
 	BUFFER_TRACE(bh, "entry");
 
+retry:
 	/*
 	 * It is safe to proceed here without the j_list_lock because the
 	 * buffers cannot be stolen by try_to_free_buffers as long as we are
@@ -1879,10 +1880,18 @@
 	 * clear the buffer dirty bit at latest at the moment when the
 	 * transaction marking the buffer as freed in the filesystem
 	 * structures is committed because from that moment on the
-	 * buffer can be reallocated and used by a different page.
+	 * block can be reallocated and used by a different page.
 	 * Since the block hasn't been freed yet but the inode has
 	 * already been added to orphan list, it is safe for us to add
 	 * the buffer to BJ_Forget list of the newest transaction.
+	 *
+	 * Also we have to clear buffer_mapped flag of a truncated buffer
+	 * because the buffer_head may be attached to the page straddling
+	 * i_size (can happen only when blocksize < pagesize) and thus the
+	 * buffer_head can be reused when the file is extended again. So we end
+	 * up keeping around invalidated buffers attached to transactions'
+	 * BJ_Forget list just to stop checkpointing code from cleaning up
+	 * the transaction this buffer was modified in.
 	 */
 	transaction = jh->b_transaction;
 	if (transaction == NULL) {
@@ -1909,13 +1918,9 @@
 			 * committed, the buffer won't be needed any
 			 * longer. */
 			JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
-			ret = __dispose_buffer(jh,
+			may_free = __dispose_buffer(jh,
 					journal->j_running_transaction);
-			journal_put_journal_head(jh);
-			spin_unlock(&journal->j_list_lock);
-			jbd_unlock_bh_state(bh);
-			spin_unlock(&journal->j_state_lock);
-			return ret;
+			goto zap_buffer;
 		} else {
 			/* There is no currently-running transaction. So the
 			 * orphan record which we wrote for this file must have
@@ -1923,13 +1928,9 @@
 			 * the committing transaction, if it exists. */
 			if (journal->j_committing_transaction) {
 				JBUFFER_TRACE(jh, "give to committing trans");
-				ret = __dispose_buffer(jh,
+				may_free = __dispose_buffer(jh,
 					journal->j_committing_transaction);
-				journal_put_journal_head(jh);
-				spin_unlock(&journal->j_list_lock);
-				jbd_unlock_bh_state(bh);
-				spin_unlock(&journal->j_state_lock);
-				return ret;
+				goto zap_buffer;
 			} else {
 				/* The orphan record's transaction has
 				 * committed.  We can cleanse this buffer */
@@ -1950,10 +1951,24 @@
 		}
 		/*
 		 * The buffer is committing, we simply cannot touch
-		 * it. So we just set j_next_transaction to the
-		 * running transaction (if there is one) and mark
-		 * buffer as freed so that commit code knows it should
-		 * clear dirty bits when it is done with the buffer.
+		 * it. If the page is straddling i_size we have to wait
+		 * for commit and try again.
+		 */
+		if (partial_page) {
+			tid_t tid = journal->j_committing_transaction->t_tid;
+
+			journal_put_journal_head(jh);
+			spin_unlock(&journal->j_list_lock);
+			jbd_unlock_bh_state(bh);
+			spin_unlock(&journal->j_state_lock);
+			log_wait_commit(journal, tid);
+			goto retry;
+		}
+		/*
+		 * OK, buffer won't be reachable after truncate. We just set
+		 * j_next_transaction to the running transaction (if there is
+		 * one) and mark buffer as freed so that commit code knows it
+		 * should clear dirty bits when it is done with the buffer.
 		 */
 		set_buffer_freed(bh);
 		if (journal->j_running_transaction && buffer_jbddirty(bh))
@@ -1976,6 +1991,14 @@
 	}
 
 zap_buffer:
+	/*
+	 * This is tricky. Although the buffer is truncated, it may be reused
+	 * if blocksize < pagesize and it is attached to the page straddling
+	 * EOF. Since the buffer might have been added to BJ_Forget list of the
+	 * running transaction, journal_get_write_access() won't clear
+	 * b_modified and credit accounting gets confused. So clear b_modified
+	 * here. */
+	jh->b_modified = 0;
 	journal_put_journal_head(jh);
 zap_buffer_no_jh:
 	spin_unlock(&journal->j_list_lock);
@@ -2024,7 +2047,8 @@
 		if (offset <= curr_off) {
 			/* This block is wholly outside the truncation point */
 			lock_buffer(bh);
-			may_free &= journal_unmap_buffer(journal, bh);
+			may_free &= journal_unmap_buffer(journal, bh,
+							 offset > 0);
 			unlock_buffer(bh);
 		}
 		curr_off = next_off;
diff -druN linux-libre-3.6-gnu/fs/jbd2/journal.c linux-libre-3.6.3-gnu/fs/jbd2/journal.c
--- linux-libre-3.6-gnu/fs/jbd2/journal.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/jbd2/journal.c	2012-10-21 12:32:56.000000000 -0400
@@ -1354,6 +1354,11 @@
 
 	BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
 	read_lock(&journal->j_state_lock);
+	/* Is it already empty? */
+	if (sb->s_start == 0) {
+		read_unlock(&journal->j_state_lock);
+		return;
+	}
 	jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
 		  journal->j_tail_sequence);
 
diff -druN linux-libre-3.6-gnu/fs/jffs2/super.c linux-libre-3.6.3-gnu/fs/jffs2/super.c
--- linux-libre-3.6-gnu/fs/jffs2/super.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/jffs2/super.c	2012-10-21 12:32:56.000000000 -0400
@@ -100,6 +100,10 @@
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 
+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
+	cancel_delayed_work_sync(&c->wbuf_dwork);
+#endif
+
 	mutex_lock(&c->alloc_sem);
 	jffs2_flush_wbuf_pad(c);
 	mutex_unlock(&c->alloc_sem);
diff -druN linux-libre-3.6-gnu/fs/jffs2/wbuf.c linux-libre-3.6.3-gnu/fs/jffs2/wbuf.c
--- linux-libre-3.6-gnu/fs/jffs2/wbuf.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/jffs2/wbuf.c	2012-10-21 12:32:56.000000000 -0400
@@ -1044,10 +1044,10 @@
 	ops.datbuf = NULL;
 
 	ret = mtd_read_oob(c->mtd, jeb->offset, &ops);
-	if (ret || ops.oobretlen != ops.ooblen) {
+	if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) {
 		pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n",
 		       jeb->offset, ops.ooblen, ops.oobretlen, ret);
-		if (!ret)
+		if (!ret || mtd_is_bitflip(ret))
 			ret = -EIO;
 		return ret;
 	}
@@ -1086,10 +1086,10 @@
 	ops.datbuf = NULL;
 
 	ret = mtd_read_oob(c->mtd, jeb->offset, &ops);
-	if (ret || ops.oobretlen != ops.ooblen) {
+	if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) {
 		pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n",
 		       jeb->offset, ops.ooblen, ops.oobretlen, ret);
-		if (!ret)
+		if (!ret || mtd_is_bitflip(ret))
 			ret = -EIO;
 		return ret;
 	}
diff -druN linux-libre-3.6-gnu/fs/lockd/mon.c linux-libre-3.6.3-gnu/fs/lockd/mon.c
--- linux-libre-3.6-gnu/fs/lockd/mon.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/lockd/mon.c	2012-10-21 12:32:56.000000000 -0400
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/utsname.h>
 #include <linux/kernel.h>
 #include <linux/ktime.h>
 #include <linux/slab.h>
@@ -19,6 +18,8 @@
 
 #include <asm/unaligned.h>
 
+#include "netns.h"
+
 #define NLMDBG_FACILITY		NLMDBG_MONITOR
 #define NSM_PROGRAM		100024
 #define NSM_VERSION		1
@@ -40,6 +41,7 @@
 	u32			proc;
 
 	char			*mon_name;
+	char			*nodename;
 };
 
 struct nsm_res {
@@ -70,7 +72,7 @@
 	};
 	struct rpc_create_args args = {
 		.net			= net,
-		.protocol		= XPRT_TRANSPORT_UDP,
+		.protocol		= XPRT_TRANSPORT_TCP,
 		.address		= (struct sockaddr *)&sin,
 		.addrsize		= sizeof(sin),
 		.servername		= "rpc.statd",
@@ -83,10 +85,54 @@
 	return rpc_create(&args);
 }
 
-static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
-			 struct net *net)
+static struct rpc_clnt *nsm_client_get(struct net *net)
 {
+	static DEFINE_MUTEX(nsm_create_mutex);
 	struct rpc_clnt	*clnt;
+	struct lockd_net *ln = net_generic(net, lockd_net_id);
+
+	spin_lock(&ln->nsm_clnt_lock);
+	if (ln->nsm_users) {
+		ln->nsm_users++;
+		clnt = ln->nsm_clnt;
+		spin_unlock(&ln->nsm_clnt_lock);
+		goto out;
+	}
+	spin_unlock(&ln->nsm_clnt_lock);
+
+	mutex_lock(&nsm_create_mutex);
+	clnt = nsm_create(net);
+	if (!IS_ERR(clnt)) {
+		ln->nsm_clnt = clnt;
+		smp_wmb();
+		ln->nsm_users = 1;
+	}
+	mutex_unlock(&nsm_create_mutex);
+out:
+	return clnt;
+}
+
+static void nsm_client_put(struct net *net)
+{
+	struct lockd_net *ln = net_generic(net, lockd_net_id);
+	struct rpc_clnt	*clnt = ln->nsm_clnt;
+	int shutdown = 0;
+
+	spin_lock(&ln->nsm_clnt_lock);
+	if (ln->nsm_users) {
+		if (--ln->nsm_users)
+			ln->nsm_clnt = NULL;
+		shutdown = !ln->nsm_users;
+	}
+	spin_unlock(&ln->nsm_clnt_lock);
+
+	if (shutdown)
+		rpc_shutdown_client(clnt);
+}
+
+static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
+			 struct rpc_clnt *clnt)
+{
 	int		status;
 	struct nsm_args args = {
 		.priv		= &nsm->sm_priv,
@@ -94,31 +140,24 @@
 		.vers		= 3,
 		.proc		= NLMPROC_NSM_NOTIFY,
 		.mon_name	= nsm->sm_mon_name,
+		.nodename	= clnt->cl_nodename,
 	};
 	struct rpc_message msg = {
 		.rpc_argp	= &args,
 		.rpc_resp	= res,
 	};
 
-	clnt = nsm_create(net);
-	if (IS_ERR(clnt)) {
-		status = PTR_ERR(clnt);
-		dprintk("lockd: failed to create NSM upcall transport, "
-				"status=%d\n", status);
-		goto out;
-	}
+	BUG_ON(clnt == NULL);
 
 	memset(res, 0, sizeof(*res));
 
 	msg.rpc_proc = &clnt->cl_procinfo[proc];
-	status = rpc_call_sync(clnt, &msg, 0);
+	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
 	if (status < 0)
 		dprintk("lockd: NSM upcall RPC failed, status=%d\n",
 				status);
 	else
 		status = 0;
-	rpc_shutdown_client(clnt);
- out:
 	return status;
 }
 
@@ -138,6 +177,7 @@
 	struct nsm_handle *nsm = host->h_nsmhandle;
 	struct nsm_res	res;
 	int		status;
+	struct rpc_clnt *clnt;
 
 	dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
 
@@ -150,7 +190,15 @@
 	 */
 	nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
 
-	status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net);
+	clnt = nsm_client_get(host->net);
+	if (IS_ERR(clnt)) {
+		status = PTR_ERR(clnt);
+		dprintk("lockd: failed to create NSM upcall transport, "
+				"status=%d, net=%p\n", status, host->net);
+		return status;
+	}
+
+	status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
 	if (unlikely(res.status != 0))
 		status = -EIO;
 	if (unlikely(status < 0)) {
@@ -182,9 +230,11 @@
 
 	if (atomic_read(&nsm->sm_count) == 1
 	 && nsm->sm_monitored && !nsm->sm_sticky) {
+		struct lockd_net *ln = net_generic(host->net, lockd_net_id);
+
 		dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
 
-		status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net);
+		status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
 		if (res.status != 0)
 			status = -EIO;
 		if (status < 0)
@@ -192,6 +242,8 @@
 					nsm->sm_name);
 		else
 			nsm->sm_monitored = 0;
+
+		nsm_client_put(host->net);
 	}
 }
 
@@ -430,7 +482,7 @@
 {
 	__be32 *p;
 
-	encode_nsm_string(xdr, utsname()->nodename);
+	encode_nsm_string(xdr, argp->nodename);
 	p = xdr_reserve_space(xdr, 4 + 4 + 4);
 	*p++ = cpu_to_be32(argp->prog);
 	*p++ = cpu_to_be32(argp->vers);
diff -druN linux-libre-3.6-gnu/fs/lockd/netns.h linux-libre-3.6.3-gnu/fs/lockd/netns.h
--- linux-libre-3.6-gnu/fs/lockd/netns.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/lockd/netns.h	2012-10-21 12:32:56.000000000 -0400
@@ -12,6 +12,10 @@
 	struct delayed_work grace_period_end;
 	struct lock_manager lockd_manager;
 	struct list_head grace_list;
+
+	spinlock_t nsm_clnt_lock;
+	unsigned int nsm_users;
+	struct rpc_clnt *nsm_clnt;
 };
 
 extern int lockd_net_id;
diff -druN linux-libre-3.6-gnu/fs/lockd/svc.c linux-libre-3.6.3-gnu/fs/lockd/svc.c
--- linux-libre-3.6-gnu/fs/lockd/svc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/lockd/svc.c	2012-10-21 12:32:56.000000000 -0400
@@ -596,6 +596,7 @@
 
 	INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
 	INIT_LIST_HEAD(&ln->grace_list);
+	spin_lock_init(&ln->nsm_clnt_lock);
 	return 0;
 }
 
diff -druN linux-libre-3.6-gnu/fs/namei.c linux-libre-3.6.3-gnu/fs/namei.c
--- linux-libre-3.6-gnu/fs/namei.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/namei.c	2012-10-21 12:32:56.000000000 -0400
@@ -692,9 +692,9 @@
 	if (parent->i_uid == inode->i_uid)
 		return 0;
 
+	audit_log_link_denied("follow_link", link);
 	path_put_conditional(link, nd);
 	path_put(&nd->path);
-	audit_log_link_denied("follow_link", link);
 	return -EACCES;
 }
 
diff -druN linux-libre-3.6-gnu/fs/nfs/blocklayout/blocklayout.c linux-libre-3.6.3-gnu/fs/nfs/blocklayout/blocklayout.c
--- linux-libre-3.6-gnu/fs/nfs/blocklayout/blocklayout.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nfs/blocklayout/blocklayout.c	2012-10-21 12:32:56.000000000 -0400
@@ -162,25 +162,39 @@
 	return bio;
 }
 
-static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
+static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw,
 				      sector_t isect, struct page *page,
 				      struct pnfs_block_extent *be,
 				      void (*end_io)(struct bio *, int err),
-				      struct parallel_io *par)
+				      struct parallel_io *par,
+				      unsigned int offset, int len)
 {
+	isect = isect + (offset >> SECTOR_SHIFT);
+	dprintk("%s: npg %d rw %d isect %llu offset %u len %d\n", __func__,
+		npg, rw, (unsigned long long)isect, offset, len);
 retry:
 	if (!bio) {
 		bio = bl_alloc_init_bio(npg, isect, be, end_io, par);
 		if (!bio)
 			return ERR_PTR(-ENOMEM);
 	}
-	if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
+	if (bio_add_page(bio, page, len, offset) < len) {
 		bio = bl_submit_bio(rw, bio);
 		goto retry;
 	}
 	return bio;
 }
 
+static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
+				      sector_t isect, struct page *page,
+				      struct pnfs_block_extent *be,
+				      void (*end_io)(struct bio *, int err),
+				      struct parallel_io *par)
+{
+	return do_add_page_to_bio(bio, npg, rw, isect, page, be,
+				  end_io, par, 0, PAGE_CACHE_SIZE);
+}
+
 /* This is basically copied from mpage_end_io_read */
 static void bl_end_io_read(struct bio *bio, int err)
 {
@@ -461,6 +475,106 @@
 	return;
 }
 
+static void
+bl_read_single_end_io(struct bio *bio, int error)
+{
+	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+	struct page *page = bvec->bv_page;
+
+	/* Only one page in bvec */
+	unlock_page(page);
+}
+
+static int
+bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be,
+		    unsigned int offset, unsigned int len)
+{
+	struct bio *bio;
+	struct page *shadow_page;
+	sector_t isect;
+	char *kaddr, *kshadow_addr;
+	int ret = 0;
+
+	dprintk("%s: offset %u len %u\n", __func__, offset, len);
+
+	shadow_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+	if (shadow_page == NULL)
+		return -ENOMEM;
+
+	bio = bio_alloc(GFP_NOIO, 1);
+	if (bio == NULL)
+		return -ENOMEM;
+
+	isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) +
+		(offset / SECTOR_SIZE);
+
+	bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
+	bio->bi_bdev = be->be_mdev;
+	bio->bi_end_io = bl_read_single_end_io;
+
+	lock_page(shadow_page);
+	if (bio_add_page(bio, shadow_page,
+			 SECTOR_SIZE, round_down(offset, SECTOR_SIZE)) == 0) {
+		unlock_page(shadow_page);
+		bio_put(bio);
+		return -EIO;
+	}
+
+	submit_bio(READ, bio);
+	wait_on_page_locked(shadow_page);
+	if (unlikely(!test_bit(BIO_UPTODATE, &bio->bi_flags))) {
+		ret = -EIO;
+	} else {
+		kaddr = kmap_atomic(page);
+		kshadow_addr = kmap_atomic(shadow_page);
+		memcpy(kaddr + offset, kshadow_addr + offset, len);
+		kunmap_atomic(kshadow_addr);
+		kunmap_atomic(kaddr);
+	}
+	__free_page(shadow_page);
+	bio_put(bio);
+
+	return ret;
+}
+
+static int
+bl_read_partial_page_sync(struct page *page, struct pnfs_block_extent *be,
+			  unsigned int dirty_offset, unsigned int dirty_len,
+			  bool full_page)
+{
+	int ret = 0;
+	unsigned int start, end;
+
+	if (full_page) {
+		start = 0;
+		end = PAGE_CACHE_SIZE;
+	} else {
+		start = round_down(dirty_offset, SECTOR_SIZE);
+		end = round_up(dirty_offset + dirty_len, SECTOR_SIZE);
+	}
+
+	dprintk("%s: offset %u len %d\n", __func__, dirty_offset, dirty_len);
+	if (!be) {
+		zero_user_segments(page, start, dirty_offset,
+				   dirty_offset + dirty_len, end);
+		if (start == 0 && end == PAGE_CACHE_SIZE &&
+		    trylock_page(page)) {
+			SetPageUptodate(page);
+			unlock_page(page);
+		}
+		return ret;
+	}
+
+	if (start != dirty_offset)
+		ret = bl_do_readpage_sync(page, be, start, dirty_offset - start);
+
+	if (!ret && (dirty_offset + dirty_len < end))
+		ret = bl_do_readpage_sync(page, be, dirty_offset + dirty_len,
+					  end - dirty_offset - dirty_len);
+
+	return ret;
+}
+
 /* Given an unmapped page, zero it or read in page for COW, page is locked
  * by caller.
  */
@@ -494,7 +608,6 @@
 	SetPageUptodate(page);
 
 cleanup:
-	bl_put_extent(cow_read);
 	if (bh)
 		free_buffer_head(bh);
 	if (ret) {
@@ -566,6 +679,7 @@
 	struct parallel_io *par = NULL;
 	loff_t offset = wdata->args.offset;
 	size_t count = wdata->args.count;
+	unsigned int pg_offset, pg_len, saved_len;
 	struct page **pages = wdata->args.pages;
 	struct page *page;
 	pgoff_t index;
@@ -674,10 +788,11 @@
 		if (!extent_length) {
 			/* We've used up the previous extent */
 			bl_put_extent(be);
+			bl_put_extent(cow_read);
 			bio = bl_submit_bio(WRITE, bio);
 			/* Get the next one */
 			be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg),
-					     isect, NULL);
+					     isect, &cow_read);
 			if (!be || !is_writable(be, isect)) {
 				header->pnfs_error = -EINVAL;
 				goto out;
@@ -694,7 +809,26 @@
 			extent_length = be->be_length -
 			    (isect - be->be_f_offset);
 		}
-		if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+
+		dprintk("%s offset %lld count %Zu\n", __func__, offset, count);
+		pg_offset = offset & ~PAGE_CACHE_MASK;
+		if (pg_offset + count > PAGE_CACHE_SIZE)
+			pg_len = PAGE_CACHE_SIZE - pg_offset;
+		else
+			pg_len = count;
+
+		saved_len = pg_len;
+		if (be->be_state == PNFS_BLOCK_INVALID_DATA &&
+		    !bl_is_sector_init(be->be_inval, isect)) {
+			ret = bl_read_partial_page_sync(pages[i], cow_read,
+							pg_offset, pg_len, true);
+			if (ret) {
+				dprintk("%s bl_read_partial_page_sync fail %d\n",
+					__func__, ret);
+				header->pnfs_error = ret;
+				goto out;
+			}
+
 			ret = bl_mark_sectors_init(be->be_inval, isect,
 						       PAGE_CACHE_SECTORS);
 			if (unlikely(ret)) {
@@ -703,15 +837,35 @@
 				header->pnfs_error = ret;
 				goto out;
 			}
+
+			/* Expand to full page write */
+			pg_offset = 0;
+			pg_len = PAGE_CACHE_SIZE;
+		} else if  ((pg_offset & (SECTOR_SIZE - 1)) ||
+			    (pg_len & (SECTOR_SIZE - 1))){
+			/* ahh, nasty case. We have to do sync full sector
+			 * read-modify-write cycles.
+			 */
+			unsigned int saved_offset = pg_offset;
+			ret = bl_read_partial_page_sync(pages[i], be, pg_offset,
+							pg_len, false);
+			pg_offset = round_down(pg_offset, SECTOR_SIZE);
+			pg_len = round_up(saved_offset + pg_len, SECTOR_SIZE)
+				 - pg_offset;
 		}
-		bio = bl_add_page_to_bio(bio, wdata->pages.npages - i, WRITE,
+
+
+		bio = do_add_page_to_bio(bio, wdata->pages.npages - i, WRITE,
 					 isect, pages[i], be,
-					 bl_end_io_write, par);
+					 bl_end_io_write, par,
+					 pg_offset, pg_len);
 		if (IS_ERR(bio)) {
 			header->pnfs_error = PTR_ERR(bio);
 			bio = NULL;
 			goto out;
 		}
+		offset += saved_len;
+		count -= saved_len;
 		isect += PAGE_CACHE_SECTORS;
 		last_isect = isect;
 		extent_length -= PAGE_CACHE_SECTORS;
@@ -729,17 +883,16 @@
 	}
 
 write_done:
-	wdata->res.count = (last_isect << SECTOR_SHIFT) - (offset);
-	if (count < wdata->res.count) {
-		wdata->res.count = count;
-	}
+	wdata->res.count = wdata->args.count;
 out:
 	bl_put_extent(be);
+	bl_put_extent(cow_read);
 	bl_submit_bio(WRITE, bio);
 	put_parallel(par);
 	return PNFS_ATTEMPTED;
 out_mds:
 	bl_put_extent(be);
+	bl_put_extent(cow_read);
 	kfree(par);
 	return PNFS_NOT_ATTEMPTED;
 }
diff -druN linux-libre-3.6-gnu/fs/nfs/blocklayout/blocklayout.h linux-libre-3.6.3-gnu/fs/nfs/blocklayout/blocklayout.h
--- linux-libre-3.6-gnu/fs/nfs/blocklayout/blocklayout.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nfs/blocklayout/blocklayout.h	2012-10-21 12:32:56.000000000 -0400
@@ -41,6 +41,7 @@
 
 #define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT)
 #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT)
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
 
 struct block_mount_id {
 	spinlock_t			bm_lock;    /* protects list */
diff -druN linux-libre-3.6-gnu/fs/nfs/client.c linux-libre-3.6.3-gnu/fs/nfs/client.c
--- linux-libre-3.6-gnu/fs/nfs/client.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nfs/client.c	2012-10-21 12:32:56.000000000 -0400
@@ -855,7 +855,6 @@
 	if (server->wsize > NFS_MAX_FILE_IO_SIZE)
 		server->wsize = NFS_MAX_FILE_IO_SIZE;
 	server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	server->pnfs_blksize = fsinfo->blksize;
 
 	server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
diff -druN linux-libre-3.6-gnu/fs/nfs/nfs4proc.c linux-libre-3.6.3-gnu/fs/nfs/nfs4proc.c
--- linux-libre-3.6-gnu/fs/nfs/nfs4proc.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nfs/nfs4proc.c	2012-10-21 12:32:56.000000000 -0400
@@ -1774,7 +1774,11 @@
 		 * informs us the stateid is unrecognized. */
 		if (status != -NFS4ERR_BAD_STATEID)
 			nfs41_free_stateid(server, stateid);
+		nfs_remove_bad_delegation(state->inode);
 
+		write_seqlock(&state->seqlock);
+		nfs4_stateid_copy(&state->stateid, &state->open_stateid);
+		write_sequnlock(&state->seqlock);
 		clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	}
 }
@@ -3362,8 +3366,11 @@
 
 	nfs_fattr_init(fsinfo->fattr);
 	error = nfs4_do_fsinfo(server, fhandle, fsinfo);
-	if (error == 0)
+	if (error == 0) {
+		/* block layout checks this! */
+		server->pnfs_blksize = fsinfo->blksize;
 		set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype);
+	}
 
 	return error;
 }
diff -druN linux-libre-3.6-gnu/fs/nfsd/nfs4idmap.c linux-libre-3.6.3-gnu/fs/nfsd/nfs4idmap.c
--- linux-libre-3.6-gnu/fs/nfsd/nfs4idmap.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nfsd/nfs4idmap.c	2012-10-21 12:32:56.000000000 -0400
@@ -598,7 +598,7 @@
 	/* Just to make sure it's null-terminated: */
 	memcpy(buf, name, namelen);
 	buf[namelen] = '\0';
-	ret = kstrtouint(name, 10, id);
+	ret = kstrtouint(buf, 10, id);
 	return ret == 0;
 }
 
diff -druN linux-libre-3.6-gnu/fs/nfsd/nfs4state.c linux-libre-3.6.3-gnu/fs/nfsd/nfs4state.c
--- linux-libre-3.6-gnu/fs/nfsd/nfs4state.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nfsd/nfs4state.c	2012-10-21 12:32:56.000000000 -0400
@@ -1223,10 +1223,26 @@
 	return true;
 }
 
+/*
+ * RFC 3530 language requires clid_inuse be returned when the
+ * "principal" associated with a requests differs from that previously
+ * used.  We use uid, gid's, and gss principal string as our best
+ * approximation.  We also don't want to allow non-gss use of a client
+ * established using gss: in theory cr_principal should catch that
+ * change, but in practice cr_principal can be null even in the gss case
+ * since gssd doesn't always pass down a principal string.
+ */
+static bool is_gss_cred(struct svc_cred *cr)
+{
+	/* Is cr_flavor one of the gss "pseudoflavors"?: */
+	return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR);
+}
+
+
 static bool
 same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
 {
-	if ((cr1->cr_flavor != cr2->cr_flavor)
+	if ((is_gss_cred(cr1) != is_gss_cred(cr2))
 		|| (cr1->cr_uid != cr2->cr_uid)
 		|| (cr1->cr_gid != cr2->cr_gid)
 		|| !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
@@ -3766,6 +3782,7 @@
 	memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
 
 	nfsd4_close_open_stateid(stp);
+	release_last_closed_stateid(oo);
 	oo->oo_last_closed_stid = stp;
 
 	if (list_empty(&oo->oo_owner.so_stateids)) {
diff -druN linux-libre-3.6-gnu/fs/nilfs2/file.c linux-libre-3.6.3-gnu/fs/nilfs2/file.c
--- linux-libre-3.6-gnu/fs/nilfs2/file.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/nilfs2/file.c	2012-10-21 12:32:56.000000000 -0400
@@ -116,6 +116,7 @@
 	if (unlikely(ret))
 		goto out;
 
+	file_update_time(vma->vm_file);
 	ret = __block_page_mkwrite(vma, vmf, nilfs_get_block);
 	if (ret) {
 		nilfs_transaction_abort(inode->i_sb);
diff -druN linux-libre-3.6-gnu/fs/proc/page.c linux-libre-3.6.3-gnu/fs/proc/page.c
--- linux-libre-3.6-gnu/fs/proc/page.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/proc/page.c	2012-10-21 12:32:56.000000000 -0400
@@ -115,7 +115,13 @@
 		u |= 1 << KPF_COMPOUND_TAIL;
 	if (PageHuge(page))
 		u |= 1 << KPF_HUGE;
-	else if (PageTransCompound(page))
+	/*
+	 * PageTransCompound can be true for non-huge compound pages (slab
+	 * pages or pages allocated by drivers with __GFP_COMP) because it
+	 * just checks PG_head/PG_tail, so we need to check PageLRU to make
+	 * sure a given page is a thp, not a non-huge compound page.
+	 */
+	else if (PageTransCompound(page) && PageLRU(compound_trans_head(page)))
 		u |= 1 << KPF_THP;
 
 	/*
diff -druN linux-libre-3.6-gnu/fs/reiserfs/inode.c linux-libre-3.6.3-gnu/fs/reiserfs/inode.c
--- linux-libre-3.6-gnu/fs/reiserfs/inode.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/reiserfs/inode.c	2012-10-21 12:32:56.000000000 -0400
@@ -1573,8 +1573,10 @@
 			reiserfs_warning(sb, "reiserfs-13077",
 				"nfsd/reiserfs, fhtype=%d, len=%d - odd",
 				fh_type, fh_len);
-		fh_type = 5;
+		fh_type = fh_len;
 	}
+	if (fh_len < 2)
+		return NULL;
 
 	return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1],
 		(fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0);
@@ -1583,6 +1585,8 @@
 struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
 		int fh_len, int fh_type)
 {
+	if (fh_type > fh_len)
+		fh_type = fh_len;
 	if (fh_type < 4)
 		return NULL;
 
diff -druN linux-libre-3.6-gnu/fs/xfs/xfs_export.c linux-libre-3.6.3-gnu/fs/xfs/xfs_export.c
--- linux-libre-3.6-gnu/fs/xfs/xfs_export.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/fs/xfs/xfs_export.c	2012-10-21 12:32:56.000000000 -0400
@@ -189,6 +189,9 @@
 	struct xfs_fid64	*fid64 = (struct xfs_fid64 *)fid;
 	struct inode		*inode = NULL;
 
+	if (fh_len < xfs_fileid_length(fileid_type))
+		return NULL;
+
 	switch (fileid_type) {
 	case FILEID_INO32_GEN_PARENT:
 		inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino,
diff -druN linux-libre-3.6-gnu/include/linux/mempolicy.h linux-libre-3.6.3-gnu/include/linux/mempolicy.h
--- linux-libre-3.6-gnu/include/linux/mempolicy.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/include/linux/mempolicy.h	2012-10-21 12:32:56.000000000 -0400
@@ -188,7 +188,7 @@
 
 struct shared_policy {
 	struct rb_root root;
-	spinlock_t lock;
+	struct mutex mutex;
 };
 
 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
diff -druN linux-libre-3.6-gnu/include/linux/mtd/nand.h linux-libre-3.6.3-gnu/include/linux/mtd/nand.h
--- linux-libre-3.6-gnu/include/linux/mtd/nand.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/include/linux/mtd/nand.h	2012-10-21 12:32:56.000000000 -0400
@@ -212,9 +212,6 @@
 #define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
 					&& (chip->page_shift > 9))
 
-/* Mask to zero out the chip options, which come from the id table */
-#define NAND_CHIPOPTIONS_MSK	0x0000ffff
-
 /* Non chip related options */
 /* This option skips the bbt scan during initialization. */
 #define NAND_SKIP_BBTSCAN	0x00010000
diff -druN linux-libre-3.6-gnu/include/linux/pci_ids.h linux-libre-3.6.3-gnu/include/linux/pci_ids.h
--- linux-libre-3.6-gnu/include/linux/pci_ids.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/include/linux/pci_ids.h	2012-10-21 12:32:56.000000000 -0400
@@ -1847,7 +1847,6 @@
 #define PCI_DEVICE_ID_SIIG_8S_20x_650	0x2081
 #define PCI_DEVICE_ID_SIIG_8S_20x_850	0x2082
 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL	0x2050
-#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL	0x2530
 
 #define PCI_VENDOR_ID_RADISYS		0x1331
 
diff -druN linux-libre-3.6-gnu/include/net/ip_fib.h linux-libre-3.6.3-gnu/include/net/ip_fib.h
--- linux-libre-3.6-gnu/include/net/ip_fib.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/include/net/ip_fib.h	2012-10-21 12:32:56.000000000 -0400
@@ -102,6 +102,7 @@
 	unsigned char		fib_dead;
 	unsigned char		fib_protocol;
 	unsigned char		fib_scope;
+	unsigned char		fib_type;
 	__be32			fib_prefsrc;
 	u32			fib_priority;
 	u32			*fib_metrics;
diff -druN linux-libre-3.6-gnu/kernel/audit.c linux-libre-3.6.3-gnu/kernel/audit.c
--- linux-libre-3.6-gnu/kernel/audit.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/audit.c	2012-10-21 12:32:56.000000000 -0400
@@ -1466,6 +1466,8 @@
 
 	ab = audit_log_start(current->audit_context, GFP_KERNEL,
 			     AUDIT_ANOM_LINK);
+	if (!ab)
+		return;
 	audit_log_format(ab, "op=%s action=denied", operation);
 	audit_log_format(ab, " pid=%d comm=", current->pid);
 	audit_log_untrustedstring(ab, current->comm);
diff -druN linux-libre-3.6-gnu/kernel/debug/kdb/kdb_io.c linux-libre-3.6.3-gnu/kernel/debug/kdb/kdb_io.c
--- linux-libre-3.6-gnu/kernel/debug/kdb/kdb_io.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/debug/kdb/kdb_io.c	2012-10-21 12:32:56.000000000 -0400
@@ -552,6 +552,7 @@
 {
 	int diag;
 	int linecount;
+	int colcount;
 	int logging, saved_loglevel = 0;
 	int saved_trap_printk;
 	int got_printf_lock = 0;
@@ -584,6 +585,10 @@
 	if (diag || linecount <= 1)
 		linecount = 24;
 
+	diag = kdbgetintenv("COLUMNS", &colcount);
+	if (diag || colcount <= 1)
+		colcount = 80;
+
 	diag = kdbgetintenv("LOGGING", &logging);
 	if (diag)
 		logging = 0;
@@ -690,7 +695,7 @@
 		gdbstub_msg_write(kdb_buffer, retlen);
 	} else {
 		if (dbg_io_ops && !dbg_io_ops->is_console) {
-			len = strlen(kdb_buffer);
+			len = retlen;
 			cp = kdb_buffer;
 			while (len--) {
 				dbg_io_ops->write_char(*cp);
@@ -709,11 +714,29 @@
 		printk(KERN_INFO "%s", kdb_buffer);
 	}
 
-	if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n'))
-		kdb_nextline++;
+	if (KDB_STATE(PAGER)) {
+		/*
+		 * Check printed string to decide how to bump the
+		 * kdb_nextline to control when the more prompt should
+		 * show up.
+		 */
+		int got = 0;
+		len = retlen;
+		while (len--) {
+			if (kdb_buffer[len] == '\n') {
+				kdb_nextline++;
+				got = 0;
+			} else if (kdb_buffer[len] == '\r') {
+				got = 0;
+			} else {
+				got++;
+			}
+		}
+		kdb_nextline += got / (colcount + 1);
+	}
 
 	/* check for having reached the LINES number of printed lines */
-	if (kdb_nextline == linecount) {
+	if (kdb_nextline >= linecount) {
 		char buf1[16] = "";
 
 		/* Watch out for recursion here.  Any routine that calls
@@ -765,7 +788,7 @@
 			kdb_grepping_flag = 0;
 			kdb_printf("\n");
 		} else if (buf1[0] == ' ') {
-			kdb_printf("\n");
+			kdb_printf("\r");
 			suspend_grep = 1; /* for this recursion */
 		} else if (buf1[0] == '\n') {
 			kdb_nextline = linecount - 1;
diff -druN linux-libre-3.6-gnu/kernel/module.c linux-libre-3.6.3-gnu/kernel/module.c
--- linux-libre-3.6-gnu/kernel/module.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/module.c	2012-10-21 12:32:56.000000000 -0400
@@ -2730,6 +2730,10 @@
 	if (strcmp(mod->name, "driverloader") == 0)
 		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
 
+	/* lve claims to be GPL but upstream won't provide source */
+	if (strcmp(mod->name, "lve") == 0)
+		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
+
 #ifdef CONFIG_MODVERSIONS
 	if ((mod->num_syms && !mod->crcs)
 	    || (mod->num_gpl_syms && !mod->gpl_crcs)
diff -druN linux-libre-3.6-gnu/kernel/rcutree.c linux-libre-3.6.3-gnu/kernel/rcutree.c
--- linux-libre-3.6-gnu/kernel/rcutree.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/rcutree.c	2012-10-21 12:32:56.000000000 -0400
@@ -305,7 +305,9 @@
 static int
 cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp);
+	return *rdp->nxttail[RCU_DONE_TAIL +
+			     ACCESS_ONCE(rsp->completed) != rdp->completed] &&
+	       !rcu_gp_in_progress(rsp);
 }
 
 /*
diff -druN linux-libre-3.6-gnu/kernel/sched/core.c linux-libre-3.6.3-gnu/kernel/sched/core.c
--- linux-libre-3.6-gnu/kernel/sched/core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/sched/core.c	2012-10-21 12:32:56.000000000 -0400
@@ -5604,7 +5604,9 @@
 		migrate_tasks(cpu);
 		BUG_ON(rq->nr_running != 1); /* the migration thread */
 		raw_spin_unlock_irqrestore(&rq->lock, flags);
+		break;
 
+	case CPU_DEAD:
 		calc_load_migrate(rq);
 		break;
 #endif
diff -druN linux-libre-3.6-gnu/kernel/sys.c linux-libre-3.6.3-gnu/kernel/sys.c
--- linux-libre-3.6-gnu/kernel/sys.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/sys.c	2012-10-21 12:32:56.000000000 -0400
@@ -368,6 +368,7 @@
 void kernel_restart(char *cmd)
 {
 	kernel_restart_prepare(cmd);
+	disable_nonboot_cpus();
 	if (!cmd)
 		printk(KERN_EMERG "Restarting system.\n");
 	else
diff -druN linux-libre-3.6-gnu/kernel/time/tick-sched.c linux-libre-3.6.3-gnu/kernel/time/tick-sched.c
--- linux-libre-3.6-gnu/kernel/time/tick-sched.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/time/tick-sched.c	2012-10-21 12:32:56.000000000 -0400
@@ -835,7 +835,7 @@
 		 */
 		if (ts->tick_stopped) {
 			touch_softlockup_watchdog();
-			if (idle_cpu(cpu))
+			if (is_idle_task(current))
 				ts->idle_jiffies++;
 		}
 		update_process_times(user_mode(regs));
diff -druN linux-libre-3.6-gnu/kernel/time/timekeeping.c linux-libre-3.6.3-gnu/kernel/time/timekeeping.c
--- linux-libre-3.6-gnu/kernel/time/timekeeping.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/time/timekeeping.c	2012-10-21 12:32:56.000000000 -0400
@@ -1111,7 +1111,7 @@
 	accumulate_nsecs_to_secs(tk);
 
 	/* Accumulate raw time */
-	raw_nsecs = tk->raw_interval << shift;
+	raw_nsecs = (u64)tk->raw_interval << shift;
 	raw_nsecs += tk->raw_time.tv_nsec;
 	if (raw_nsecs >= NSEC_PER_SEC) {
 		u64 raw_secs = raw_nsecs;
diff -druN linux-libre-3.6-gnu/kernel/timer.c linux-libre-3.6.3-gnu/kernel/timer.c
--- linux-libre-3.6-gnu/kernel/timer.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/timer.c	2012-10-21 12:32:56.000000000 -0400
@@ -63,6 +63,7 @@
 #define TVR_SIZE (1 << TVR_BITS)
 #define TVN_MASK (TVN_SIZE - 1)
 #define TVR_MASK (TVR_SIZE - 1)
+#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1))
 
 struct tvec {
 	struct list_head vec[TVN_SIZE];
@@ -358,11 +359,12 @@
 		vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
 	} else {
 		int i;
-		/* If the timeout is larger than 0xffffffff on 64-bit
-		 * architectures then we use the maximum timeout:
+		/* If the timeout is larger than MAX_TVAL (on 64-bit
+		 * architectures or with CONFIG_BASE_SMALL=1) then we
+		 * use the maximum timeout.
 		 */
-		if (idx > 0xffffffffUL) {
-			idx = 0xffffffffUL;
+		if (idx > MAX_TVAL) {
+			idx = MAX_TVAL;
 			expires = idx + base->timer_jiffies;
 		}
 		i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
diff -druN linux-libre-3.6-gnu/kernel/workqueue.c linux-libre-3.6.3-gnu/kernel/workqueue.c
--- linux-libre-3.6-gnu/kernel/workqueue.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/kernel/workqueue.c	2012-10-21 12:32:56.000000000 -0400
@@ -1927,10 +1927,9 @@
 		*nextp = n;
 }
 
-static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
+static void cwq_activate_delayed_work(struct work_struct *work)
 {
-	struct work_struct *work = list_first_entry(&cwq->delayed_works,
-						    struct work_struct, entry);
+	struct cpu_workqueue_struct *cwq = get_work_cwq(work);
 
 	trace_workqueue_activate_work(work);
 	move_linked_works(work, &cwq->pool->worklist, NULL);
@@ -1938,6 +1937,14 @@
 	cwq->nr_active++;
 }
 
+static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
+{
+	struct work_struct *work = list_first_entry(&cwq->delayed_works,
+						    struct work_struct, entry);
+
+	cwq_activate_delayed_work(work);
+}
+
 /**
  * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight
  * @cwq: cwq of interest
@@ -2073,7 +2080,9 @@
 
 	spin_unlock_irq(&gcwq->lock);
 
+	smp_wmb();	/* paired with test_and_set_bit(PENDING) */
 	work_clear_pending(work);
+
 	lock_map_acquire_read(&cwq->wq->lockdep_map);
 	lock_map_acquire(&lockdep_map);
 	trace_workqueue_execute_start(work);
@@ -2844,6 +2853,18 @@
 		smp_rmb();
 		if (gcwq == get_work_gcwq(work)) {
 			debug_work_deactivate(work);
+
+			/*
+			 * A delayed work item cannot be grabbed directly
+			 * because it might have linked NO_COLOR work items
+			 * which, if left on the delayed_list, will confuse
+			 * cwq->nr_active management later on and cause
+			 * stall.  Make sure the work item is activated
+			 * before grabbing.
+			 */
+			if (*work_data_bits(work) & WORK_STRUCT_DELAYED)
+				cwq_activate_delayed_work(work);
+
 			list_del_init(&work->entry);
 			cwq_dec_nr_in_flight(get_work_cwq(work),
 				get_work_color(work),
diff -druN linux-libre-3.6-gnu/lib/gcd.c linux-libre-3.6.3-gnu/lib/gcd.c
--- linux-libre-3.6-gnu/lib/gcd.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/lib/gcd.c	2012-10-21 12:32:56.000000000 -0400
@@ -9,6 +9,9 @@
 
 	if (a < b)
 		swap(a, b);
+
+	if (!b)
+		return a;
 	while ((r = a % b) != 0) {
 		a = b;
 		b = r;
diff -druN linux-libre-3.6-gnu/Makefile linux-libre-3.6.3-gnu/Makefile
--- linux-libre-3.6-gnu/Makefile	2012-09-30 20:49:59.000000000 -0400
+++ linux-libre-3.6.3-gnu/Makefile	2012-10-21 13:49:08.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 6
-SUBLEVEL = 0
+SUBLEVEL = 3
 EXTRAVERSION =-gnu
 NAME = Terrified Chipmunk
 
diff -druN linux-libre-3.6-gnu/mm/hugetlb.c linux-libre-3.6.3-gnu/mm/hugetlb.c
--- linux-libre-3.6-gnu/mm/hugetlb.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/mm/hugetlb.c	2012-10-21 12:32:56.000000000 -0400
@@ -2481,7 +2481,8 @@
 	 * from page cache lookup which is in HPAGE_SIZE units.
 	 */
 	address = address & huge_page_mask(h);
-	pgoff = vma_hugecache_offset(h, vma, address);
+	pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) +
+			vma->vm_pgoff;
 	mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
 
 	/*
diff -druN linux-libre-3.6-gnu/mm/mempolicy.c linux-libre-3.6.3-gnu/mm/mempolicy.c
--- linux-libre-3.6-gnu/mm/mempolicy.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/mm/mempolicy.c	2012-10-21 12:32:56.000000000 -0400
@@ -607,6 +607,42 @@
 	return first;
 }
 
+/*
+ * Apply policy to a single VMA
+ * This must be called with the mmap_sem held for writing.
+ */
+static int vma_replace_policy(struct vm_area_struct *vma,
+						struct mempolicy *pol)
+{
+	int err;
+	struct mempolicy *old;
+	struct mempolicy *new;
+
+	pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
+		 vma->vm_start, vma->vm_end, vma->vm_pgoff,
+		 vma->vm_ops, vma->vm_file,
+		 vma->vm_ops ? vma->vm_ops->set_policy : NULL);
+
+	new = mpol_dup(pol);
+	if (IS_ERR(new))
+		return PTR_ERR(new);
+
+	if (vma->vm_ops && vma->vm_ops->set_policy) {
+		err = vma->vm_ops->set_policy(vma, new);
+		if (err)
+			goto err_out;
+	}
+
+	old = vma->vm_policy;
+	vma->vm_policy = new; /* protected by mmap_sem */
+	mpol_put(old);
+
+	return 0;
+ err_out:
+	mpol_put(new);
+	return err;
+}
+
 /* Step 2: apply policy to a range and do splits. */
 static int mbind_range(struct mm_struct *mm, unsigned long start,
 		       unsigned long end, struct mempolicy *new_pol)
@@ -655,23 +691,9 @@
 			if (err)
 				goto out;
 		}
-
-		/*
-		 * Apply policy to a single VMA. The reference counting of
-		 * policy for vma_policy linkages has already been handled by
-		 * vma_merge and split_vma as necessary. If this is a shared
-		 * policy then ->set_policy will increment the reference count
-		 * for an sp node.
-		 */
-		pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
-			vma->vm_start, vma->vm_end, vma->vm_pgoff,
-			vma->vm_ops, vma->vm_file,
-			vma->vm_ops ? vma->vm_ops->set_policy : NULL);
-		if (vma->vm_ops && vma->vm_ops->set_policy) {
-			err = vma->vm_ops->set_policy(vma, new_pol);
-			if (err)
-				goto out;
-		}
+		err = vma_replace_policy(vma, new_pol);
+		if (err)
+			goto out;
 	}
 
  out:
@@ -1530,8 +1552,18 @@
 									addr);
 			if (vpol)
 				pol = vpol;
-		} else if (vma->vm_policy)
+		} else if (vma->vm_policy) {
 			pol = vma->vm_policy;
+
+			/*
+			 * shmem_alloc_page() passes MPOL_F_SHARED policy with
+			 * a pseudo vma whose vma->vm_ops=NULL. Take a reference
+			 * count on these policies which will be dropped by
+			 * mpol_cond_put() later
+			 */
+			if (mpol_needs_cond_ref(pol))
+				mpol_get(pol);
+		}
 	}
 	if (!pol)
 		pol = &default_policy;
@@ -2061,7 +2093,7 @@
  */
 
 /* lookup first element intersecting start-end */
-/* Caller holds sp->lock */
+/* Caller holds sp->mutex */
 static struct sp_node *
 sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end)
 {
@@ -2125,36 +2157,50 @@
 
 	if (!sp->root.rb_node)
 		return NULL;
-	spin_lock(&sp->lock);
+	mutex_lock(&sp->mutex);
 	sn = sp_lookup(sp, idx, idx+1);
 	if (sn) {
 		mpol_get(sn->policy);
 		pol = sn->policy;
 	}
-	spin_unlock(&sp->lock);
+	mutex_unlock(&sp->mutex);
 	return pol;
 }
 
+static void sp_free(struct sp_node *n)
+{
+	mpol_put(n->policy);
+	kmem_cache_free(sn_cache, n);
+}
+
 static void sp_delete(struct shared_policy *sp, struct sp_node *n)
 {
 	pr_debug("deleting %lx-l%lx\n", n->start, n->end);
 	rb_erase(&n->nd, &sp->root);
-	mpol_put(n->policy);
-	kmem_cache_free(sn_cache, n);
+	sp_free(n);
 }
 
 static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
 				struct mempolicy *pol)
 {
-	struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL);
+	struct sp_node *n;
+	struct mempolicy *newpol;
 
+	n = kmem_cache_alloc(sn_cache, GFP_KERNEL);
 	if (!n)
 		return NULL;
+
+	newpol = mpol_dup(pol);
+	if (IS_ERR(newpol)) {
+		kmem_cache_free(sn_cache, n);
+		return NULL;
+	}
+	newpol->flags |= MPOL_F_SHARED;
+
 	n->start = start;
 	n->end = end;
-	mpol_get(pol);
-	pol->flags |= MPOL_F_SHARED;	/* for unref */
-	n->policy = pol;
+	n->policy = newpol;
+
 	return n;
 }
 
@@ -2162,10 +2208,10 @@
 static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
 				 unsigned long end, struct sp_node *new)
 {
-	struct sp_node *n, *new2 = NULL;
+	struct sp_node *n;
+	int ret = 0;
 
-restart:
-	spin_lock(&sp->lock);
+	mutex_lock(&sp->mutex);
 	n = sp_lookup(sp, start, end);
 	/* Take care of old policies in the same range. */
 	while (n && n->start < end) {
@@ -2178,16 +2224,14 @@
 		} else {
 			/* Old policy spanning whole new range. */
 			if (n->end > end) {
+				struct sp_node *new2;
+				new2 = sp_alloc(end, n->end, n->policy);
 				if (!new2) {
-					spin_unlock(&sp->lock);
-					new2 = sp_alloc(end, n->end, n->policy);
-					if (!new2)
-						return -ENOMEM;
-					goto restart;
+					ret = -ENOMEM;
+					goto out;
 				}
 				n->end = start;
 				sp_insert(sp, new2);
-				new2 = NULL;
 				break;
 			} else
 				n->end = start;
@@ -2198,12 +2242,9 @@
 	}
 	if (new)
 		sp_insert(sp, new);
-	spin_unlock(&sp->lock);
-	if (new2) {
-		mpol_put(new2->policy);
-		kmem_cache_free(sn_cache, new2);
-	}
-	return 0;
+out:
+	mutex_unlock(&sp->mutex);
+	return ret;
 }
 
 /**
@@ -2221,7 +2262,7 @@
 	int ret;
 
 	sp->root = RB_ROOT;		/* empty tree == default mempolicy */
-	spin_lock_init(&sp->lock);
+	mutex_init(&sp->mutex);
 
 	if (mpol) {
 		struct vm_area_struct pvma;
@@ -2275,7 +2316,7 @@
 	}
 	err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new);
 	if (err && new)
-		kmem_cache_free(sn_cache, new);
+		sp_free(new);
 	return err;
 }
 
@@ -2287,16 +2328,14 @@
 
 	if (!p->root.rb_node)
 		return;
-	spin_lock(&p->lock);
+	mutex_lock(&p->mutex);
 	next = rb_first(&p->root);
 	while (next) {
 		n = rb_entry(next, struct sp_node, nd);
 		next = rb_next(&n->nd);
-		rb_erase(&n->nd, &p->root);
-		mpol_put(n->policy);
-		kmem_cache_free(sn_cache, n);
+		sp_delete(p, n);
 	}
-	spin_unlock(&p->lock);
+	mutex_unlock(&p->mutex);
 }
 
 /* assumes fs == KERNEL_DS */
diff -druN linux-libre-3.6-gnu/mm/shmem.c linux-libre-3.6.3-gnu/mm/shmem.c
--- linux-libre-3.6-gnu/mm/shmem.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/mm/shmem.c	2012-10-21 12:32:56.000000000 -0400
@@ -2366,12 +2366,14 @@
 {
 	struct inode *inode;
 	struct dentry *dentry = NULL;
-	u64 inum = fid->raw[2];
-	inum = (inum << 32) | fid->raw[1];
+	u64 inum;
 
 	if (fh_len < 3)
 		return NULL;
 
+	inum = fid->raw[2];
+	inum = (inum << 32) | fid->raw[1];
+
 	inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
 			shmem_match, fid->raw);
 	if (inode) {
diff -druN linux-libre-3.6-gnu/mm/slab.c linux-libre-3.6.3-gnu/mm/slab.c
--- linux-libre-3.6-gnu/mm/slab.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/mm/slab.c	2012-10-21 12:32:56.000000000 -0400
@@ -1781,9 +1781,6 @@
 
 	slab_state = UP;
 
-	/* Annotate slab for lockdep -- annotate the malloc caches */
-	init_lock_keys();
-
 	/* 6) resize the head arrays to their final sizes */
 	mutex_lock(&slab_mutex);
 	list_for_each_entry(cachep, &slab_caches, list)
@@ -1791,6 +1788,9 @@
 			BUG();
 	mutex_unlock(&slab_mutex);
 
+	/* Annotate slab for lockdep -- annotate the malloc caches */
+	init_lock_keys();
+
 	/* Done! */
 	slab_state = FULL;
 
diff -druN linux-libre-3.6-gnu/mm/truncate.c linux-libre-3.6.3-gnu/mm/truncate.c
--- linux-libre-3.6-gnu/mm/truncate.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/mm/truncate.c	2012-10-21 12:32:56.000000000 -0400
@@ -394,11 +394,12 @@
 	if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL))
 		return 0;
 
+	clear_page_mlock(page);
+
 	spin_lock_irq(&mapping->tree_lock);
 	if (PageDirty(page))
 		goto failed;
 
-	clear_page_mlock(page);
 	BUG_ON(page_has_private(page));
 	__delete_from_page_cache(page);
 	spin_unlock_irq(&mapping->tree_lock);
diff -druN linux-libre-3.6-gnu/net/8021q/vlan_core.c linux-libre-3.6.3-gnu/net/8021q/vlan_core.c
--- linux-libre-3.6-gnu/net/8021q/vlan_core.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/8021q/vlan_core.c	2012-10-21 12:32:56.000000000 -0400
@@ -105,7 +105,6 @@
 		return NULL;
 	memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
 	skb->mac_header += VLAN_HLEN;
-	skb_reset_mac_len(skb);
 	return skb;
 }
 
@@ -139,6 +138,8 @@
 
 	skb_reset_network_header(skb);
 	skb_reset_transport_header(skb);
+	skb_reset_mac_len(skb);
+
 	return skb;
 
 err_free:
diff -druN linux-libre-3.6-gnu/net/core/pktgen.c linux-libre-3.6.3-gnu/net/core/pktgen.c
--- linux-libre-3.6-gnu/net/core/pktgen.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/core/pktgen.c	2012-10-21 12:32:56.000000000 -0400
@@ -2927,7 +2927,7 @@
 		  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
 		  pkt_dev->pkt_overhead;
 
-	if (datalen < sizeof(struct pktgen_hdr)) {
+	if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) {
 		datalen = sizeof(struct pktgen_hdr);
 		net_info_ratelimited("increased datalen to %d\n", datalen);
 	}
diff -druN linux-libre-3.6-gnu/net/ipv4/fib_semantics.c linux-libre-3.6.3-gnu/net/ipv4/fib_semantics.c
--- linux-libre-3.6-gnu/net/ipv4/fib_semantics.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/ipv4/fib_semantics.c	2012-10-21 12:32:56.000000000 -0400
@@ -314,6 +314,7 @@
 		    nfi->fib_scope == fi->fib_scope &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
 		    nfi->fib_priority == fi->fib_priority &&
+		    nfi->fib_type == fi->fib_type &&
 		    memcmp(nfi->fib_metrics, fi->fib_metrics,
 			   sizeof(u32) * RTAX_MAX) == 0 &&
 		    ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 &&
@@ -833,6 +834,7 @@
 	fi->fib_flags = cfg->fc_flags;
 	fi->fib_priority = cfg->fc_priority;
 	fi->fib_prefsrc = cfg->fc_prefsrc;
+	fi->fib_type = cfg->fc_type;
 
 	fi->fib_nhs = nhs;
 	change_nexthops(fi) {
diff -druN linux-libre-3.6-gnu/net/ipv6/addrconf.c linux-libre-3.6.3-gnu/net/ipv6/addrconf.c
--- linux-libre-3.6-gnu/net/ipv6/addrconf.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/ipv6/addrconf.c	2012-10-21 12:32:56.000000000 -0400
@@ -788,10 +788,16 @@
 		struct in6_addr prefix;
 		struct rt6_info *rt;
 		struct net *net = dev_net(ifp->idev->dev);
+		struct flowi6 fl6 = {};
+
 		ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
-		rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
+		fl6.flowi6_oif = ifp->idev->dev->ifindex;
+		fl6.daddr = prefix;
+		rt = (struct rt6_info *)ip6_route_lookup(net, &fl6,
+							 RT6_LOOKUP_F_IFACE);
 
-		if (rt && addrconf_is_prefix_route(rt)) {
+		if (rt != net->ipv6.ip6_null_entry &&
+		    addrconf_is_prefix_route(rt)) {
 			if (onlink == 0) {
 				ip6_del_rt(rt);
 				rt = NULL;
diff -druN linux-libre-3.6-gnu/net/ipv6/route.c linux-libre-3.6.3-gnu/net/ipv6/route.c
--- linux-libre-3.6-gnu/net/ipv6/route.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/ipv6/route.c	2012-10-21 12:32:56.000000000 -0400
@@ -1589,17 +1589,18 @@
 	struct fib6_table *table;
 	struct net *net = dev_net(rt->dst.dev);
 
-	if (rt == net->ipv6.ip6_null_entry)
-		return -ENOENT;
+	if (rt == net->ipv6.ip6_null_entry) {
+		err = -ENOENT;
+		goto out;
+	}
 
 	table = rt->rt6i_table;
 	write_lock_bh(&table->tb6_lock);
-
 	err = fib6_del(rt, info);
-	dst_release(&rt->dst);
-
 	write_unlock_bh(&table->tb6_lock);
 
+out:
+	dst_release(&rt->dst);
 	return err;
 }
 
diff -druN linux-libre-3.6-gnu/net/mac80211/status.c linux-libre-3.6.3-gnu/net/mac80211/status.c
--- linux-libre-3.6-gnu/net/mac80211/status.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/mac80211/status.c	2012-10-21 12:32:56.000000000 -0400
@@ -34,7 +34,7 @@
 		skb_queue_len(&local->skb_queue_unreliable);
 	while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
 	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
-		dev_kfree_skb_irq(skb);
+		ieee80211_free_txskb(hw, skb);
 		tmp--;
 		I802_DEBUG_INC(local->tx_status_drop);
 	}
@@ -159,7 +159,7 @@
 			   "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
 			   skb_queue_len(&sta->tx_filtered[ac]),
 			   !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
-	dev_kfree_skb(skb);
+	ieee80211_free_txskb(&local->hw, skb);
 }
 
 static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
diff -druN linux-libre-3.6-gnu/net/mac80211/tx.c linux-libre-3.6.3-gnu/net/mac80211/tx.c
--- linux-libre-3.6-gnu/net/mac80211/tx.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/mac80211/tx.c	2012-10-21 12:32:56.000000000 -0400
@@ -354,7 +354,7 @@
 			total += skb_queue_len(&sta->ps_tx_buf[ac]);
 			if (skb) {
 				purged++;
-				dev_kfree_skb(skb);
+				ieee80211_free_txskb(&local->hw, skb);
 				break;
 			}
 		}
@@ -466,7 +466,7 @@
 			ps_dbg(tx->sdata,
 			       "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
 			       sta->sta.addr, ac);
-			dev_kfree_skb(old);
+			ieee80211_free_txskb(&local->hw, old);
 		} else
 			tx->local->total_ps_buffered++;
 
@@ -1103,7 +1103,7 @@
 		spin_unlock(&tx->sta->lock);
 
 		if (purge_skb)
-			dev_kfree_skb(purge_skb);
+			ieee80211_free_txskb(&tx->local->hw, purge_skb);
 	}
 
 	/* reset session timer */
@@ -1214,7 +1214,7 @@
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (WARN_ON_ONCE(q >= local->hw.queues)) {
 			__skb_unlink(skb, skbs);
-			dev_kfree_skb(skb);
+			ieee80211_free_txskb(&local->hw, skb);
 			continue;
 		}
 #endif
@@ -1356,7 +1356,7 @@
 	if (unlikely(res == TX_DROP)) {
 		I802_DEBUG_INC(tx->local->tx_handlers_drop);
 		if (tx->skb)
-			dev_kfree_skb(tx->skb);
+			ieee80211_free_txskb(&tx->local->hw, tx->skb);
 		else
 			__skb_queue_purge(&tx->skbs);
 		return -1;
@@ -1393,7 +1393,7 @@
 	res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
 
 	if (unlikely(res_prepare == TX_DROP)) {
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(&local->hw, skb);
 		goto out;
 	} else if (unlikely(res_prepare == TX_QUEUED)) {
 		goto out;
@@ -1466,7 +1466,7 @@
 	headroom = max_t(int, 0, headroom);
 
 	if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(&local->hw, skb);
 		rcu_read_unlock();
 		return;
 	}
@@ -2060,8 +2060,10 @@
 		head_need += IEEE80211_ENCRYPT_HEADROOM;
 		head_need += local->tx_headroom;
 		head_need = max_t(int, 0, head_need);
-		if (ieee80211_skb_resize(sdata, skb, head_need, true))
-			goto fail;
+		if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
+			ieee80211_free_txskb(&local->hw, skb);
+			return NETDEV_TX_OK;
+		}
 	}
 
 	if (encaps_data) {
@@ -2196,7 +2198,7 @@
 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 			if (WARN_ON(!info->control.vif)) {
-				kfree_skb(skb);
+				ieee80211_free_txskb(&local->hw, skb);
 				continue;
 			}
 
diff -druN linux-libre-3.6-gnu/net/sunrpc/xprtsock.c linux-libre-3.6.3-gnu/net/sunrpc/xprtsock.c
--- linux-libre-3.6-gnu/net/sunrpc/xprtsock.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/net/sunrpc/xprtsock.c	2012-10-21 12:32:56.000000000 -0400
@@ -1025,6 +1025,16 @@
 	read_unlock_bh(&sk->sk_callback_lock);
 }
 
+/*
+ * Helper function to force a TCP close if the server is sending
+ * junk and/or it has put us in CLOSE_WAIT
+ */
+static void xs_tcp_force_close(struct rpc_xprt *xprt)
+{
+	set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+	xprt_force_disconnect(xprt);
+}
+
 static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
 {
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1051,7 +1061,7 @@
 	/* Sanity check of the record length */
 	if (unlikely(transport->tcp_reclen < 8)) {
 		dprintk("RPC:       invalid TCP record fragment length\n");
-		xprt_force_disconnect(xprt);
+		xs_tcp_force_close(xprt);
 		return;
 	}
 	dprintk("RPC:       reading TCP record fragment of length %d\n",
@@ -1132,7 +1142,7 @@
 		break;
 	default:
 		dprintk("RPC:       invalid request message type\n");
-		xprt_force_disconnect(&transport->xprt);
+		xs_tcp_force_close(&transport->xprt);
 	}
 	xs_tcp_check_fraghdr(transport);
 }
@@ -1455,6 +1465,8 @@
 static void xs_sock_mark_closed(struct rpc_xprt *xprt)
 {
 	smp_mb__before_clear_bit();
+	clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
+	clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
 	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
 	clear_bit(XPRT_CLOSING, &xprt->state);
 	smp_mb__after_clear_bit();
@@ -1512,8 +1524,8 @@
 		break;
 	case TCP_CLOSE_WAIT:
 		/* The server initiated a shutdown of the socket */
-		xprt_force_disconnect(xprt);
 		xprt->connect_cookie++;
+		xs_tcp_force_close(xprt);
 	case TCP_CLOSING:
 		/*
 		 * If the server closed down the connection, make sure that
@@ -2199,8 +2211,7 @@
 		/* We're probably in TIME_WAIT. Get rid of existing socket,
 		 * and retry
 		 */
-		set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
-		xprt_force_disconnect(xprt);
+		xs_tcp_force_close(xprt);
 		break;
 	case -ECONNREFUSED:
 	case -ECONNRESET:
diff -druN linux-libre-3.6-gnu/scripts/gcc-version.sh linux-libre-3.6.3-gnu/scripts/gcc-version.sh
--- linux-libre-3.6-gnu/scripts/gcc-version.sh	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/gcc-version.sh	2012-10-21 12:32:56.000000000 -0400
@@ -22,10 +22,10 @@
 	exit 1
 fi
 
-MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1)
-MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1)
+MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1)
+MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1)
 if [ "x$with_patchlevel" != "x" ] ; then
-	PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1)
+	PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)
 	printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
 else
 	printf "%02d%02d\\n" $MAJOR $MINOR
diff -druN linux-libre-3.6-gnu/scripts/gcc-x86_32-has-stack-protector.sh linux-libre-3.6.3-gnu/scripts/gcc-x86_32-has-stack-protector.sh
--- linux-libre-3.6-gnu/scripts/gcc-x86_32-has-stack-protector.sh	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/gcc-x86_32-has-stack-protector.sh	2012-10-21 12:32:56.000000000 -0400
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
 if [ "$?" -eq "0" ] ; then
 	echo y
 else
diff -druN linux-libre-3.6-gnu/scripts/gcc-x86_64-has-stack-protector.sh linux-libre-3.6.3-gnu/scripts/gcc-x86_64-has-stack-protector.sh
--- linux-libre-3.6-gnu/scripts/gcc-x86_64-has-stack-protector.sh	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/gcc-x86_64-has-stack-protector.sh	2012-10-21 12:32:56.000000000 -0400
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
 if [ "$?" -eq "0" ] ; then
 	echo y
 else
diff -druN linux-libre-3.6-gnu/scripts/Kbuild.include linux-libre-3.6.3-gnu/scripts/Kbuild.include
--- linux-libre-3.6-gnu/scripts/Kbuild.include	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/Kbuild.include	2012-10-21 12:32:56.000000000 -0400
@@ -98,24 +98,24 @@
 # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
 
 as-option = $(call try-run,\
-	$(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
+	$(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
 
 # as-instr
 # Usage: cflags-y += $(call as-instr,instr,option1,option2)
 
 as-instr = $(call try-run,\
-	printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
+	printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
 
 cc-option = $(call try-run,\
-	$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
+	$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn,-march=winchip-c6)
 cc-option-yn = $(call try-run,\
-	$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
+	$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
 
 # cc-option-align
 # Prefix align with either -falign or -malign
@@ -125,7 +125,7 @@
 # cc-disable-warning
 # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
 cc-disable-warning = $(call try-run,\
-	$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+	$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
 
 # cc-version
 # Usage gcc-ver := $(call cc-version)
@@ -143,7 +143,7 @@
 # cc-ldoption
 # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
 cc-ldoption = $(call try-run,\
-	$(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
+	$(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # ld-option
 # Usage: LDFLAGS += $(call ld-option, -X)
@@ -209,7 +209,7 @@
 # >$< substitution to preserve $ when reloading .cmd file
 # note: when using inline perl scripts [perl -e '...$$t=1;...']
 # in $(cmd_xxx) double $$ your perl vars
-make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
 
 # Find any prerequisites that is newer than target or that does not exist.
 # PHONY targets skipped in both cases.
diff -druN linux-libre-3.6-gnu/scripts/kconfig/check.sh linux-libre-3.6.3-gnu/scripts/kconfig/check.sh
--- linux-libre-3.6-gnu/scripts/kconfig/check.sh	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/kconfig/check.sh	2012-10-21 12:32:56.000000000 -0400
@@ -1,6 +1,6 @@
 #!/bin/sh
 # Needed for systems without gettext
-$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
+$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
 #include <libintl.h>
 int main()
 {
diff -druN linux-libre-3.6-gnu/scripts/kconfig/lxdialog/check-lxdialog.sh linux-libre-3.6.3-gnu/scripts/kconfig/lxdialog/check-lxdialog.sh
--- linux-libre-3.6-gnu/scripts/kconfig/lxdialog/check-lxdialog.sh	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/kconfig/lxdialog/check-lxdialog.sh	2012-10-21 12:32:56.000000000 -0400
@@ -38,7 +38,7 @@
 
 # Check if we can link to ncurses
 check() {
-        $cc -xc - -o $tmp 2>/dev/null <<'EOF'
+        $cc -x c - -o $tmp 2>/dev/null <<'EOF'
 #include CURSES_LOC
 main() {}
 EOF
diff -druN linux-libre-3.6-gnu/scripts/kconfig/streamline_config.pl linux-libre-3.6.3-gnu/scripts/kconfig/streamline_config.pl
--- linux-libre-3.6-gnu/scripts/kconfig/streamline_config.pl	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/kconfig/streamline_config.pl	2012-10-21 12:32:56.000000000 -0400
@@ -605,6 +605,8 @@
 	if (defined($configs{$1})) {
 	    if ($localyesconfig) {
 	        $setconfigs{$1} = 'y';
+		print "$1=y\n";
+		next;
 	    } else {
 	        $setconfigs{$1} = $2;
 	    }
diff -druN linux-libre-3.6-gnu/scripts/package/buildtar linux-libre-3.6.3-gnu/scripts/package/buildtar
--- linux-libre-3.6-gnu/scripts/package/buildtar	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/scripts/package/buildtar	2012-10-21 12:32:56.000000000 -0400
@@ -109,7 +109,7 @@
 	if tar --owner=root --group=root --help >/dev/null 2>&1; then
 		opts="--owner=root --group=root"
 	fi
-	tar cf - . $opts | ${compress} > "${tarball}${file_ext}"
+	tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}"
 )
 
 echo "Tarball successfully created in ${tarball}${file_ext}"
diff -druN linux-libre-3.6-gnu/security/yama/yama_lsm.c linux-libre-3.6.3-gnu/security/yama/yama_lsm.c
--- linux-libre-3.6-gnu/security/yama/yama_lsm.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/security/yama/yama_lsm.c	2012-10-21 12:32:56.000000000 -0400
@@ -143,7 +143,7 @@
 		if (arg2 == 0) {
 			yama_ptracer_del(NULL, myself);
 			rc = 0;
-		} else if (arg2 == PR_SET_PTRACER_ANY) {
+		} else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) {
 			rc = yama_ptracer_add(NULL, myself);
 		} else {
 			struct task_struct *tracer;
diff -druN linux-libre-3.6-gnu/sound/drivers/aloop.c linux-libre-3.6.3-gnu/sound/drivers/aloop.c
--- linux-libre-3.6-gnu/sound/drivers/aloop.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/drivers/aloop.c	2012-10-21 12:32:56.000000000 -0400
@@ -120,6 +120,7 @@
 	unsigned int last_drift;
 	unsigned long last_jiffies;
 	struct timer_list timer;
+	spinlock_t timer_lock;
 };
 
 static struct platform_device *devices[SNDRV_CARDS];
@@ -170,6 +171,7 @@
 	unsigned long tick;
 	unsigned int rate_shift = get_rate_shift(dpcm);
 
+	spin_lock(&dpcm->timer_lock);
 	if (rate_shift != dpcm->pcm_rate_shift) {
 		dpcm->pcm_rate_shift = rate_shift;
 		dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -182,12 +184,15 @@
 	tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
 	dpcm->timer.expires = jiffies + tick;
 	add_timer(&dpcm->timer);
+	spin_unlock(&dpcm->timer_lock);
 }
 
 static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
 {
+	spin_lock(&dpcm->timer_lock);
 	del_timer(&dpcm->timer);
 	dpcm->timer.expires = 0;
+	spin_unlock(&dpcm->timer_lock);
 }
 
 #define CABLE_VALID_PLAYBACK	(1 << SNDRV_PCM_STREAM_PLAYBACK)
@@ -667,6 +672,7 @@
 	dpcm->substream = substream;
 	setup_timer(&dpcm->timer, loopback_timer_function,
 		    (unsigned long)dpcm);
+	spin_lock_init(&dpcm->timer_lock);
 
 	cable = loopback->cables[substream->number][dev];
 	if (!cable) {
diff -druN linux-libre-3.6-gnu/sound/pci/ac97/ac97_codec.c linux-libre-3.6.3-gnu/sound/pci/ac97/ac97_codec.c
--- linux-libre-3.6-gnu/sound/pci/ac97/ac97_codec.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/ac97/ac97_codec.c	2012-10-21 12:32:56.000000000 -0400
@@ -1271,6 +1271,8 @@
 		tmp.index = ac97->num;
 		kctl = snd_ctl_new1(&tmp, ac97);
 	}
+	if (!kctl)
+		return -ENOMEM;
 	if (reg >= AC97_PHONE && reg <= AC97_PCM)
 		set_tlv_db_scale(kctl, db_scale_5bit_12db_max);
 	else
diff -druN linux-libre-3.6-gnu/sound/pci/emu10k1/emu10k1_main.c linux-libre-3.6.3-gnu/sound/pci/emu10k1/emu10k1_main.c
--- linux-libre-3.6-gnu/sound/pci/emu10k1/emu10k1_main.c	2012-09-30 21:03:47.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/emu10k1/emu10k1_main.c	2012-10-21 14:10:33.000000000 -0400
@@ -1411,6 +1411,15 @@
 	 .ca0108_chip = 1,
 	 .spk71 = 1,
 	 .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
+	/* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */
+	/* This is MAEM8986, 0202 is MAEM8980 */
+	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102,
+	 .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]",
+	 .id = "EMU1010",
+	 .emu10k2_chip = 1,
+	 .ca0108_chip = 1,
+	 .spk71 = 1,
+	 .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */
 	/* Tested by James@superbug.co.uk 8th July 2005. */
 	/* This is MAEM8810, 0202 is MAEM8820 */
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
diff -druN linux-libre-3.6-gnu/sound/pci/hda/hda_codec.c linux-libre-3.6.3-gnu/sound/pci/hda/hda_codec.c
--- linux-libre-3.6-gnu/sound/pci/hda/hda_codec.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/hda/hda_codec.c	2012-10-21 12:32:56.000000000 -0400
@@ -3580,7 +3580,7 @@
 /*
  * call suspend and power-down; used both from PM and power-save
  */
-static void hda_call_codec_suspend(struct hda_codec *codec)
+static void hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
 {
 	if (codec->patch_ops.suspend)
 		codec->patch_ops.suspend(codec);
@@ -3589,7 +3589,9 @@
 			    codec->afg ? codec->afg : codec->mfg,
 			    AC_PWRST_D3);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
-	cancel_delayed_work(&codec->power_work);
+	/* Cancel delayed work if we aren't currently running from it. */
+	if (!in_wq)
+		cancel_delayed_work_sync(&codec->power_work);
 	spin_lock(&codec->power_lock);
 	snd_hda_update_power_acct(codec);
 	trace_hda_power_down(codec);
@@ -4410,7 +4412,7 @@
 	}
 	spin_unlock(&codec->power_lock);
 
-	hda_call_codec_suspend(codec);
+	hda_call_codec_suspend(codec, true);
 	if (bus->ops.pm_notify)
 		bus->ops.pm_notify(bus);
 }
@@ -5076,7 +5078,7 @@
 
 	list_for_each_entry(codec, &bus->codec_list, list) {
 		if (hda_codec_is_power_on(codec))
-			hda_call_codec_suspend(codec);
+			hda_call_codec_suspend(codec, false);
 	}
 	return 0;
 }
diff -druN linux-libre-3.6-gnu/sound/pci/hda/hda_intel.c linux-libre-3.6.3-gnu/sound/pci/hda/hda_intel.c
--- linux-libre-3.6-gnu/sound/pci/hda/hda_intel.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/hda/hda_intel.c	2012-10-21 12:32:56.000000000 -0400
@@ -487,6 +487,7 @@
 
 	/* VGA-switcheroo setup */
 	unsigned int use_vga_switcheroo:1;
+	unsigned int vga_switcheroo_registered:1;
 	unsigned int init_failed:1; /* delayed init failed */
 	unsigned int disabled:1; /* disabled by VGA-switcher */
 
@@ -538,6 +539,7 @@
 #define AZX_DCAPS_ALIGN_BUFSIZE	(1 << 22)	/* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)	/* BDLE in 4k boundary */
 #define AZX_DCAPS_POSFIX_COMBO  (1 << 24)	/* Use COMBO as default */
+#define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)	/* Take LPIB as delay */
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -2120,6 +2122,30 @@
 
 	if (pos >= azx_dev->bufsize)
 		pos = 0;
+
+	/* calculate runtime delay from LPIB */
+	if (azx_dev->substream->runtime &&
+	    chip->position_fix[stream] == POS_FIX_POSBUF &&
+	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
+		unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
+		int delay;
+		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+			delay = pos - lpib_pos;
+		else
+			delay = lpib_pos - pos;
+		if (delay < 0)
+			delay += azx_dev->bufsize;
+		if (delay >= azx_dev->period_bytes) {
+			snd_printk(KERN_WARNING SFX
+				   "Unstable LPIB (%d >= %d); "
+				   "disabling LPIB delay counting\n",
+				   delay, azx_dev->period_bytes);
+			delay = 0;
+			chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
+		}
+		azx_dev->substream->runtime->delay =
+			bytes_to_frames(azx_dev->substream->runtime, delay);
+	}
 	return pos;
 }
 
@@ -2534,7 +2560,9 @@
 		if (disabled) {
 			azx_suspend(&pci->dev);
 			chip->disabled = true;
-			snd_hda_lock_devices(chip->bus);
+			if (snd_hda_lock_devices(chip->bus))
+				snd_printk(KERN_WARNING SFX
+					   "Cannot lock devices!\n");
 		} else {
 			snd_hda_unlock_devices(chip->bus);
 			chip->disabled = false;
@@ -2577,14 +2605,20 @@
 
 static int __devinit register_vga_switcheroo(struct azx *chip)
 {
+	int err;
+
 	if (!chip->use_vga_switcheroo)
 		return 0;
 	/* FIXME: currently only handling DIS controller
 	 * is there any machine with two switchable HDMI audio controllers?
 	 */
-	return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
+	err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
 						    VGA_SWITCHEROO_DIS,
 						    chip->bus != NULL);
+	if (err < 0)
+		return err;
+	chip->vga_switcheroo_registered = 1;
+	return 0;
 }
 #else
 #define init_vga_switcheroo(chip)		/* NOP */
@@ -2604,7 +2638,8 @@
 	if (use_vga_switcheroo(chip)) {
 		if (chip->disabled && chip->bus)
 			snd_hda_unlock_devices(chip->bus);
-		vga_switcheroo_unregister_client(chip->pci);
+		if (chip->vga_switcheroo_registered)
+			vga_switcheroo_unregister_client(chip->pci);
 	}
 
 	if (chip->initialized) {
@@ -2952,14 +2987,6 @@
 	}
 
  ok:
-	err = register_vga_switcheroo(chip);
-	if (err < 0) {
-		snd_printk(KERN_ERR SFX
-			   "Error registering VGA-switcheroo client\n");
-		azx_free(chip);
-		return err;
-	}
-
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
 	if (err < 0) {
 		snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
@@ -3186,6 +3213,13 @@
 
 	pci_set_drvdata(pci, card);
 
+	err = register_vga_switcheroo(chip);
+	if (err < 0) {
+		snd_printk(KERN_ERR SFX
+			   "Error registering VGA-switcheroo client\n");
+		goto out_free;
+	}
+
 	dev++;
 	return 0;
 
@@ -3260,7 +3294,7 @@
 	/* CPT */
 	{ PCI_DEVICE(0x8086, 0x1c20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
 	/* PBG */
 	{ PCI_DEVICE(0x8086, 0x1d20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
@@ -3268,23 +3302,26 @@
 	/* Panther Point */
 	{ PCI_DEVICE(0x8086, 0x1e20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
 	/* Lynx Point */
 	{ PCI_DEVICE(0x8086, 0x8c20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
 	/* Lynx Point-LP */
 	{ PCI_DEVICE(0x8086, 0x9c20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
 	/* Lynx Point-LP */
 	{ PCI_DEVICE(0x8086, 0x9c21),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
 	/* Haswell */
 	{ PCI_DEVICE(0x8086, 0x0c0c),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+	{ PCI_DEVICE(0x8086, 0x0d0c),
+	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
+	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
 	/* SCH */
 	{ PCI_DEVICE(0x8086, 0x811b),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
diff -druN linux-libre-3.6-gnu/sound/pci/hda/patch_cirrus.c linux-libre-3.6.3-gnu/sound/pci/hda/patch_cirrus.c
--- linux-libre-3.6-gnu/sound/pci/hda/patch_cirrus.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/hda/patch_cirrus.c	2012-10-21 12:32:56.000000000 -0400
@@ -1417,7 +1417,7 @@
 	return 0;
 
  error:
-	kfree(codec->spec);
+	cs_free(codec);
 	codec->spec = NULL;
 	return err;
 }
@@ -1974,7 +1974,7 @@
 	return 0;
 
  error:
-	kfree(codec->spec);
+	cs_free(codec);
 	codec->spec = NULL;
 	return err;
 }
@@ -1999,7 +1999,7 @@
 	return 0;
 
  error:
-	kfree(codec->spec);
+	cs_free(codec);
 	codec->spec = NULL;
 	return err;
 }
diff -druN linux-libre-3.6-gnu/sound/pci/hda/patch_conexant.c linux-libre-3.6.3-gnu/sound/pci/hda/patch_conexant.c
--- linux-libre-3.6-gnu/sound/pci/hda/patch_conexant.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/hda/patch_conexant.c	2012-10-21 12:32:56.000000000 -0400
@@ -4462,6 +4462,7 @@
 	SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
 	SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
 	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
+	SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
 	{}
 };
diff -druN linux-libre-3.6-gnu/sound/pci/hda/patch_realtek.c linux-libre-3.6.3-gnu/sound/pci/hda/patch_realtek.c
--- linux-libre-3.6-gnu/sound/pci/hda/patch_realtek.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/hda/patch_realtek.c	2012-10-21 12:32:56.000000000 -0400
@@ -611,6 +611,8 @@
 {
 	struct alc_spec *spec = codec->spec;
 
+	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
+		return;
 	/* check LO jack only when it's different from HP */
 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
 		return;
@@ -2627,8 +2629,10 @@
 			return "PCM";
 		break;
 	}
-	if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
+	if (ch >= ARRAY_SIZE(channel_name)) {
+		snd_BUG();
 		return "PCM";
+	}
 
 	return channel_name[ch];
 }
@@ -6334,6 +6338,12 @@
 
 	spec = codec->spec;
 
+	alc_pick_fixup(codec, alc269_fixup_models,
+		       alc269_fixup_tbl, alc269_fixups);
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+
+	alc_auto_parse_customize_define(codec);
+
 	if (codec->vendor_id == 0x10ec0269) {
 		spec->codec_variant = ALC269_TYPE_ALC269VA;
 		switch (alc_get_coef0(codec) & 0x00f0) {
@@ -6361,12 +6371,6 @@
 		alc269_fill_coef(codec);
 	}
 
-	alc_pick_fixup(codec, alc269_fixup_models,
-		       alc269_fixup_tbl, alc269_fixups);
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-
-	alc_auto_parse_customize_define(codec);
-
 	/* automatic parse from the BIOS config */
 	err = alc269_parse_auto_config(codec);
 	if (err < 0)
diff -druN linux-libre-3.6-gnu/sound/pci/hda/patch_via.c linux-libre-3.6.3-gnu/sound/pci/hda/patch_via.c
--- linux-libre-3.6-gnu/sound/pci/hda/patch_via.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/pci/hda/patch_via.c	2012-10-21 12:32:56.000000000 -0400
@@ -118,6 +118,8 @@
 };
 
 struct via_spec {
+	struct hda_gen_spec gen;
+
 	/* codec parameterization */
 	const struct snd_kcontrol_new *mixers[6];
 	unsigned int num_mixers;
@@ -246,6 +248,7 @@
 	/* VT1708BCE & VT1708S are almost same */
 	if (spec->codec_type == VT1708BCE)
 		spec->codec_type = VT1708S;
+	snd_hda_gen_init(&spec->gen);
 	return spec;
 }
 
@@ -1628,6 +1631,7 @@
 	vt1708_stop_hp_work(spec);
 	kfree(spec->bind_cap_vol);
 	kfree(spec->bind_cap_sw);
+	snd_hda_gen_free(&spec->gen);
 	kfree(spec);
 }
 
@@ -1672,7 +1676,8 @@
 	struct via_spec *spec = codec->spec;
 
 	if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] &&
-	    (spec->codec_type != VT1708 || spec->vt1708_jack_detect))
+	    (spec->codec_type != VT1708 || spec->vt1708_jack_detect) &&
+	    is_jack_detectable(codec, spec->autocfg.hp_pins[0]))
 		present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
 
 	if (spec->smart51_enabled)
@@ -3669,6 +3674,32 @@
 		update_power_state(codec, 0x21, AC_PWRST_D3);
 }
 
+/*
+ * pin fix-up
+ */
+enum {
+	VIA_FIXUP_INTMIC_BOOST,
+};
+
+static void via_fixup_intmic_boost(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+		override_mic_boost(codec, 0x30, 0, 2, 40);
+}
+
+static const struct hda_fixup via_fixups[] = {
+	[VIA_FIXUP_INTMIC_BOOST] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = via_fixup_intmic_boost,
+	},
+};
+
+static const struct snd_pci_quirk vt2002p_fixups[] = {
+	SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
+	{}
+};
+
 /* patch for vt2002P */
 static int patch_vt2002P(struct hda_codec *codec)
 {
@@ -3685,6 +3716,9 @@
 	override_mic_boost(codec, 0x29, 0, 3, 40);
 	add_secret_dac_path(codec);
 
+	snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
 	/* automatic parse from the BIOS config */
 	err = via_parse_auto_config(codec);
 	if (err < 0) {
diff -druN linux-libre-3.6-gnu/sound/soc/codecs/wm2200.c linux-libre-3.6.3-gnu/sound/soc/codecs/wm2200.c
--- linux-libre-3.6-gnu/sound/soc/codecs/wm2200.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/soc/codecs/wm2200.c	2012-10-21 12:32:56.000000000 -0400
@@ -1028,7 +1028,7 @@
 		 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
 		 digital_tlv),
 SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
-	   WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+	   WM2200_SPK1R_MUTE_SHIFT, 1, 1),
 };
 
 WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
@@ -2091,6 +2091,7 @@
 
 	switch (wm2200->rev) {
 	case 0:
+	case 1:
 		ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
 					    ARRAY_SIZE(wm2200_reva_patch));
 		if (ret != 0) {
diff -druN linux-libre-3.6-gnu/sound/soc/codecs/wm5110.c linux-libre-3.6.3-gnu/sound/soc/codecs/wm5110.c
--- linux-libre-3.6-gnu/sound/soc/codecs/wm5110.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/soc/codecs/wm5110.c	2012-10-21 12:32:56.000000000 -0400
@@ -869,6 +869,8 @@
 	ARIZONA_ADC_DIGITAL_VOLUME_2R,
 	ARIZONA_ADC_DIGITAL_VOLUME_3L,
 	ARIZONA_ADC_DIGITAL_VOLUME_3R,
+	ARIZONA_ADC_DIGITAL_VOLUME_4L,
+	ARIZONA_ADC_DIGITAL_VOLUME_4R,
 
 	ARIZONA_DAC_DIGITAL_VOLUME_1L,
 	ARIZONA_DAC_DIGITAL_VOLUME_1R,
@@ -880,6 +882,8 @@
 	ARIZONA_DAC_DIGITAL_VOLUME_4R,
 	ARIZONA_DAC_DIGITAL_VOLUME_5L,
 	ARIZONA_DAC_DIGITAL_VOLUME_5R,
+	ARIZONA_DAC_DIGITAL_VOLUME_6L,
+	ARIZONA_DAC_DIGITAL_VOLUME_6R,
 };
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
diff -druN linux-libre-3.6-gnu/sound/soc/codecs/wm9712.c linux-libre-3.6.3-gnu/sound/soc/codecs/wm9712.c
--- linux-libre-3.6-gnu/sound/soc/codecs/wm9712.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/soc/codecs/wm9712.c	2012-10-21 12:32:56.000000000 -0400
@@ -146,7 +146,7 @@
 SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1),
 SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1),
 
-SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
+SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),
 SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
 SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0),
 SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
diff -druN linux-libre-3.6-gnu/sound/soc/codecs/wm_hubs.c linux-libre-3.6.3-gnu/sound/soc/codecs/wm_hubs.c
--- linux-libre-3.6-gnu/sound/soc/codecs/wm_hubs.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/soc/codecs/wm_hubs.c	2012-10-21 12:32:56.000000000 -0400
@@ -634,6 +634,11 @@
 
 	snd_soc_update_bits(codec, WM8993_CLASS_W_0,
 			    WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable);
+
+	snd_soc_write(codec, WM8993_LEFT_OUTPUT_VOLUME,
+		      snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME));
+	snd_soc_write(codec, WM8993_RIGHT_OUTPUT_VOLUME,
+		      snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME));
 }
 EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
 
diff -druN linux-libre-3.6-gnu/sound/soc/omap/omap-abe-twl6040.c linux-libre-3.6.3-gnu/sound/soc/omap/omap-abe-twl6040.c
--- linux-libre-3.6-gnu/sound/soc/omap/omap-abe-twl6040.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/soc/omap/omap-abe-twl6040.c	2012-10-21 12:32:56.000000000 -0400
@@ -190,7 +190,7 @@
 	twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
 	twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
 	twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
-	twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
+	twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator");
 	twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
 	twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
 	twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
diff -druN linux-libre-3.6-gnu/sound/soc/sh/fsi.c linux-libre-3.6.3-gnu/sound/soc/sh/fsi.c
--- linux-libre-3.6-gnu/sound/soc/sh/fsi.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/soc/sh/fsi.c	2012-10-21 12:32:56.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/workqueue.h>
 #include <sound/soc.h>
 #include <sound/sh_fsi.h>
 
@@ -223,7 +224,7 @@
 	 */
 	struct dma_chan		*chan;
 	struct sh_dmae_slave	slave; /* see fsi_handler_init() */
-	struct tasklet_struct	tasklet;
+	struct work_struct	work;
 	dma_addr_t		dma;
 };
 
@@ -1085,9 +1086,9 @@
 	snd_pcm_period_elapsed(io->substream);
 }
 
-static void fsi_dma_do_tasklet(unsigned long data)
+static void fsi_dma_do_work(struct work_struct *work)
 {
-	struct fsi_stream *io = (struct fsi_stream *)data;
+	struct fsi_stream *io = container_of(work, struct fsi_stream, work);
 	struct fsi_priv *fsi = fsi_stream_to_priv(io);
 	struct snd_soc_dai *dai;
 	struct dma_async_tx_descriptor *desc;
@@ -1129,7 +1130,7 @@
 	 * FIXME
 	 *
 	 * In DMAEngine case, codec and FSI cannot be started simultaneously
-	 * since FSI is using tasklet.
+	 * since FSI is using the scheduler work queue.
 	 * Therefore, in capture case, probably FSI FIFO will have got
 	 * overflow error in this point.
 	 * in that case, DMA cannot start transfer until error was cleared.
@@ -1153,7 +1154,7 @@
 
 static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	tasklet_schedule(&io->tasklet);
+	schedule_work(&io->work);
 
 	return 0;
 }
@@ -1195,14 +1196,14 @@
 		return fsi_stream_probe(fsi, dev);
 	}
 
-	tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+	INIT_WORK(&io->work, fsi_dma_do_work);
 
 	return 0;
 }
 
 static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	tasklet_kill(&io->tasklet);
+	cancel_work_sync(&io->work);
 
 	fsi_stream_stop(fsi, io);
 
diff -druN linux-libre-3.6-gnu/sound/usb/card.h linux-libre-3.6.3-gnu/sound/usb/card.h
--- linux-libre-3.6-gnu/sound/usb/card.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/card.h	2012-10-21 12:32:56.000000000 -0400
@@ -92,6 +92,8 @@
 	unsigned char silence_value;
 	unsigned int stride;
 	int iface, alt_idx;
+	int skip_packets;		/* quirks for devices to ignore the first n packets
+					   in a stream */
 
 	spinlock_t lock;
 	struct list_head list;
diff -druN linux-libre-3.6-gnu/sound/usb/endpoint.c linux-libre-3.6.3-gnu/sound/usb/endpoint.c
--- linux-libre-3.6-gnu/sound/usb/endpoint.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/endpoint.c	2012-10-21 12:32:56.000000000 -0400
@@ -31,6 +31,7 @@
 #include "card.h"
 #include "endpoint.h"
 #include "pcm.h"
+#include "quirks.h"
 
 #define EP_FLAG_ACTIVATED	0
 #define EP_FLAG_RUNNING		1
@@ -170,6 +171,11 @@
 {
 	struct urb *urb = urb_ctx->urb;
 
+	if (unlikely(ep->skip_packets > 0)) {
+		ep->skip_packets--;
+		return;
+	}
+
 	if (ep->sync_slave)
 		snd_usb_handle_sync_urb(ep->sync_slave, ep, urb);
 
@@ -828,6 +834,8 @@
 	ep->unlink_mask = 0;
 	ep->phase = 0;
 
+	snd_usb_endpoint_start_quirk(ep);
+
 	/*
 	 * If this endpoint has a data endpoint as implicit feedback source,
 	 * don't start the urbs here. Instead, mark them all as available,
diff -druN linux-libre-3.6-gnu/sound/usb/helper.c linux-libre-3.6.3-gnu/sound/usb/helper.c
--- linux-libre-3.6-gnu/sound/usb/helper.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/helper.c	2012-10-21 12:32:56.000000000 -0400
@@ -21,6 +21,7 @@
 
 #include "usbaudio.h"
 #include "helper.h"
+#include "quirks.h"
 
 /*
  * combine bytes and get an integer value
@@ -97,6 +98,10 @@
 		memcpy(data, buf, size);
 		kfree(buf);
 	}
+
+	snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype,
+			      value, index, data, size);
+
 	return err;
 }
 
diff -druN linux-libre-3.6-gnu/sound/usb/mixer.c linux-libre-3.6.3-gnu/sound/usb/mixer.c
--- linux-libre-3.6-gnu/sound/usb/mixer.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/mixer.c	2012-10-21 12:32:56.000000000 -0400
@@ -1267,6 +1267,13 @@
 		/* disable non-functional volume control */
 		master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME);
 		break;
+	case USB_ID(0x1130, 0xf211):
+		snd_printk(KERN_INFO
+			   "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n");
+		/* disable non-functional volume control */
+		channels = 0;
+		break;
+
 	}
 	if (channels > 0)
 		first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize);
diff -druN linux-libre-3.6-gnu/sound/usb/quirks.c linux-libre-3.6.3-gnu/sound/usb/quirks.c
--- linux-libre-3.6-gnu/sound/usb/quirks.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/quirks.c	2012-10-21 12:32:56.000000000 -0400
@@ -761,3 +761,27 @@
 	}
 }
 
+void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
+{
+	/*
+	 * "Playback Design" products send bogus feedback data at the start
+	 * of the stream. Ignore them.
+	 */
+	if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) &&
+	    ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
+		ep->skip_packets = 4;
+}
+
+void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
+			   __u8 request, __u8 requesttype, __u16 value,
+			   __u16 index, void *data, __u16 size)
+{
+	/*
+	 * "Playback Design" products need a 20ms delay after each
+	 * class compliant request
+	 */
+	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) &&
+	    (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+		mdelay(20);
+}
+
diff -druN linux-libre-3.6-gnu/sound/usb/quirks.h linux-libre-3.6.3-gnu/sound/usb/quirks.h
--- linux-libre-3.6-gnu/sound/usb/quirks.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/quirks.h	2012-10-21 12:32:56.000000000 -0400
@@ -1,6 +1,10 @@
 #ifndef __USBAUDIO_QUIRKS_H
 #define __USBAUDIO_QUIRKS_H
 
+struct audioformat;
+struct snd_usb_endpoint;
+struct snd_usb_substream;
+
 int snd_usb_create_quirk(struct snd_usb_audio *chip,
 			 struct usb_interface *iface,
 			 struct usb_driver *driver,
@@ -20,4 +24,10 @@
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 				 struct audioformat *fp);
 
+void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
+
+void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
+			   __u8 request, __u8 requesttype, __u16 value,
+			   __u16 index, void *data, __u16 size);
+
 #endif /* __USBAUDIO_QUIRKS_H */
diff -druN linux-libre-3.6-gnu/sound/usb/quirks-table.h linux-libre-3.6.3-gnu/sound/usb/quirks-table.h
--- linux-libre-3.6-gnu/sound/usb/quirks-table.h	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/sound/usb/quirks-table.h	2012-10-21 12:32:56.000000000 -0400
@@ -2781,6 +2781,59 @@
 	}
 },
 
+/* Microsoft XboxLive Headset/Xbox Communicator */
+{
+	USB_DEVICE(0x045e, 0x0283),
+	.bInterfaceClass = USB_CLASS_PER_INTERFACE,
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Microsoft",
+		.product_name = "XboxLive Headset/Xbox Communicator",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = &(const struct snd_usb_audio_quirk[]) {
+			{
+				/* playback */
+				.ifnum = 0,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S16_LE,
+					.channels = 1,
+					.iface = 0,
+					.altsetting = 0,
+					.altset_idx = 0,
+					.attributes = 0,
+					.endpoint = 0x04,
+					.ep_attr = 0x05,
+					.rates = SNDRV_PCM_RATE_CONTINUOUS,
+					.rate_min = 22050,
+					.rate_max = 22050
+				}
+			},
+			{
+				/* capture */
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S16_LE,
+					.channels = 1,
+					.iface = 1,
+					.altsetting = 0,
+					.altset_idx = 0,
+					.attributes = 0,
+					.endpoint = 0x85,
+					.ep_attr = 0x05,
+					.rates = SNDRV_PCM_RATE_CONTINUOUS,
+					.rate_min = 16000,
+					.rate_max = 16000
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 {
 	/*
 	 * Some USB MIDI devices don't have an audio control interface,
diff -druN linux-libre-3.6-gnu/tools/hv/hv_kvp_daemon.c linux-libre-3.6.3-gnu/tools/hv/hv_kvp_daemon.c
--- linux-libre-3.6-gnu/tools/hv/hv_kvp_daemon.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/tools/hv/hv_kvp_daemon.c	2012-10-21 12:32:56.000000000 -0400
@@ -106,7 +106,7 @@
 
 	if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) {
 		syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 }
 
@@ -118,7 +118,7 @@
 	if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) {
 		perror("fcntl");
 		syslog(LOG_ERR, "Failed to release the lock pool: %d", pool);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 }
 
@@ -137,14 +137,19 @@
 	if (!filep) {
 		kvp_release_lock(pool);
 		syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 
 	bytes_written = fwrite(kvp_file_info[pool].records,
 				sizeof(struct kvp_record),
 				kvp_file_info[pool].num_records, filep);
 
-	fflush(filep);
+	if (ferror(filep) || fclose(filep)) {
+		kvp_release_lock(pool);
+		syslog(LOG_ERR, "Failed to write file, pool: %d", pool);
+		exit(EXIT_FAILURE);
+	}
+
 	kvp_release_lock(pool);
 }
 
@@ -163,14 +168,19 @@
 	if (!filep) {
 		kvp_release_lock(pool);
 		syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
-	while (!feof(filep)) {
+	for (;;) {
 		readp = &record[records_read];
 		records_read += fread(readp, sizeof(struct kvp_record),
 					ENTRIES_PER_BLOCK * num_blocks,
 					filep);
 
+		if (ferror(filep)) {
+			syslog(LOG_ERR, "Failed to read file, pool: %d", pool);
+			exit(EXIT_FAILURE);
+		}
+
 		if (!feof(filep)) {
 			/*
 			 * We have more data to read.
@@ -180,7 +190,7 @@
 
 			if (record == NULL) {
 				syslog(LOG_ERR, "malloc failed");
-				exit(-1);
+				exit(EXIT_FAILURE);
 			}
 			continue;
 		}
@@ -191,6 +201,7 @@
 	kvp_file_info[pool].records = record;
 	kvp_file_info[pool].num_records = records_read;
 
+	fclose(filep);
 	kvp_release_lock(pool);
 }
 static int kvp_file_init(void)
@@ -208,7 +219,7 @@
 	if (access("/var/opt/hyperv", F_OK)) {
 		if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) {
 			syslog(LOG_ERR, " Failed to create /var/opt/hyperv");
-			exit(-1);
+			exit(EXIT_FAILURE);
 		}
 	}
 
@@ -232,12 +243,18 @@
 			fclose(filep);
 			return 1;
 		}
-		while (!feof(filep)) {
+		for (;;) {
 			readp = &record[records_read];
 			records_read += fread(readp, sizeof(struct kvp_record),
 					ENTRIES_PER_BLOCK,
 					filep);
 
+			if (ferror(filep)) {
+				syslog(LOG_ERR, "Failed to read file, pool: %d",
+				       i);
+				exit(EXIT_FAILURE);
+			}
+
 			if (!feof(filep)) {
 				/*
 				 * We have more data to read.
@@ -657,13 +674,13 @@
 
 	if (kvp_file_init()) {
 		syslog(LOG_ERR, "Failed to initialize the pools");
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 
 	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
 	if (fd < 0) {
 		syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 	addr.nl_family = AF_NETLINK;
 	addr.nl_pad = 0;
@@ -675,7 +692,7 @@
 	if (error < 0) {
 		syslog(LOG_ERR, "bind failed; error:%d", error);
 		close(fd);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 	sock_opt = addr.nl_groups;
 	setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
@@ -695,7 +712,7 @@
 	if (len < 0) {
 		syslog(LOG_ERR, "netlink_send failed; error:%d", len);
 		close(fd);
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 
 	pfd.fd = fd;
@@ -863,7 +880,7 @@
 		len = netlink_send(fd, incoming_cn_msg);
 		if (len < 0) {
 			syslog(LOG_ERR, "net_link send failed; error:%d", len);
-			exit(-1);
+			exit(EXIT_FAILURE);
 		}
 	}
 
diff -druN linux-libre-3.6-gnu/tools/lguest/lguest.c linux-libre-3.6.3-gnu/tools/lguest/lguest.c
--- linux-libre-3.6-gnu/tools/lguest/lguest.c	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/tools/lguest/lguest.c	2012-10-21 12:32:56.000000000 -0400
@@ -1299,6 +1299,7 @@
 	dev->feature_len = 0;
 	dev->num_vq = 0;
 	dev->running = false;
+	dev->next = NULL;
 
 	/*
 	 * Append to device list.  Prepending to a single-linked list is
diff -druN linux-libre-3.6-gnu/tools/perf/Makefile linux-libre-3.6.3-gnu/tools/perf/Makefile
--- linux-libre-3.6-gnu/tools/perf/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/tools/perf/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -62,7 +62,7 @@
 	ARCH := x86
 	IS_X86_64 := 0
 	ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
-		IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
+		IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
 	endif
 	ifeq (${IS_X86_64}, 1)
 		RAW_ARCH := x86_64
diff -druN linux-libre-3.6-gnu/tools/power/cpupower/Makefile linux-libre-3.6.3-gnu/tools/power/cpupower/Makefile
--- linux-libre-3.6-gnu/tools/power/cpupower/Makefile	2012-09-30 19:47:46.000000000 -0400
+++ linux-libre-3.6.3-gnu/tools/power/cpupower/Makefile	2012-10-21 12:32:56.000000000 -0400
@@ -111,7 +111,7 @@
 export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
 
 # check if compiler option is supported
-cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
+cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
 
 # use '-Os' optimization if available, else use -O2
 OPTIMIZATION := $(call cc-supports,-Os,-O2)
