diff -druNp linux-libre-3.8-gnu1/arch/alpha/kernel/sys_nautilus.c linux-libre-3.8.13-gnu1/arch/alpha/kernel/sys_nautilus.c
--- linux-libre-3.8-gnu1/arch/alpha/kernel/sys_nautilus.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/alpha/kernel/sys_nautilus.c	2013-05-11 16:57:46.000000000 -0400
@@ -188,6 +188,10 @@ nautilus_machine_check(unsigned long vec
 extern void free_reserved_mem(void *, void *);
 extern void pcibios_claim_one_bus(struct pci_bus *);
 
+static struct resource irongate_io = {
+	.name	= "Irongate PCI IO",
+	.flags	= IORESOURCE_IO,
+};
 static struct resource irongate_mem = {
 	.name	= "Irongate PCI MEM",
 	.flags	= IORESOURCE_MEM,
@@ -209,6 +213,7 @@ nautilus_init_pci(void)
 
 	irongate = pci_get_bus_and_slot(0, 0);
 	bus->self = irongate;
+	bus->resource[0] = &irongate_io;
 	bus->resource[1] = &irongate_mem;
 
 	pci_bus_size_bridges(bus);
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9260.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9260.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9260.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9260.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -158,8 +158,8 @@
 				usart1 {
 					pinctrl_usart1: usart1-0 {
 						atmel,pins =
-							<2 6 0x1 0x1	/* PB6 periph A with pullup */
-							 2 7 0x1 0x0>;	/* PB7 periph A */
+							<1 6 0x1 0x1	/* PB6 periph A with pullup */
+							 1 7 0x1 0x0>;	/* PB7 periph A */
 					};
 
 					pinctrl_usart1_rts: usart1_rts-0 {
@@ -194,18 +194,18 @@
 				usart3 {
 					pinctrl_usart3: usart3-0 {
 						atmel,pins =
-							<2 10 0x1 0x1	/* PB10 periph A with pullup */
-							 2 11 0x1 0x0>;	/* PB11 periph A */
+							<1 10 0x1 0x1	/* PB10 periph A with pullup */
+							 1 11 0x1 0x0>;	/* PB11 periph A */
 					};
 
 					pinctrl_usart3_rts: usart3_rts-0 {
 						atmel,pins =
-							<3 8 0x2 0x0>;	/* PB8 periph B */
+							<2 8 0x2 0x0>;	/* PC8 periph B */
 					};
 
 					pinctrl_usart3_cts: usart3_cts-0 {
 						atmel,pins =
-							<3 10 0x2 0x0>;	/* PB10 periph B */
+							<2 10 0x2 0x0>;	/* PC10 periph B */
 					};
 				};
 
@@ -220,8 +220,8 @@
 				uart1 {
 					pinctrl_uart1: uart1-0 {
 						atmel,pins =
-							<2 12 0x1 0x1	/* PB12 periph A with pullup */
-							 2 13 0x1 0x0>;	/* PB13 periph A */
+							<1 12 0x1 0x1	/* PB12 periph A with pullup */
+							 1 13 0x1 0x0>;	/* PB13 periph A */
 					};
 				};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g15.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g15.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g15.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g15.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -10,7 +10,7 @@
 
 / {
 	model = "Atmel AT91SAM9G15 SoC";
-	compatible = "atmel, at91sam9g15, atmel,at91sam9x5";
+	compatible = "atmel,at91sam9g15", "atmel,at91sam9x5";
 
 	ahb {
 		apb {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g15ek.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g15ek.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g15ek.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g15ek.dts	2013-05-11 16:57:46.000000000 -0400
@@ -11,6 +11,6 @@
 /include/ "at91sam9x5ek.dtsi"
 
 / {
-	model = "Atmel AT91SAM9G25-EK";
+	model = "Atmel AT91SAM9G15-EK";
 	compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
 };
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g25.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g25.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g25.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g25.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -10,7 +10,7 @@
 
 / {
 	model = "Atmel AT91SAM9G25 SoC";
-	compatible = "atmel, at91sam9g25, atmel,at91sam9x5";
+	compatible = "atmel,at91sam9g25", "atmel,at91sam9x5";
 
 	ahb {
 		apb {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g35.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g35.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9g35.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9g35.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -10,7 +10,7 @@
 
 / {
 	model = "Atmel AT91SAM9G35 SoC";
-	compatible = "atmel, at91sam9g35, atmel,at91sam9x5";
+	compatible = "atmel,at91sam9g35", "atmel,at91sam9x5";
 
 	ahb {
 		apb {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9n12.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9n12.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9n12.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9n12.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -324,8 +324,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf801c000 0x4000>;
 				interrupts = <5 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
@@ -335,8 +333,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8020000 0x4000>;
 				interrupts = <6 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
@@ -346,8 +342,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8024000 0x4000>;
 				interrupts = <7 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
@@ -357,8 +351,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8028000 0x4000>;
 				interrupts = <8 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart3>;
 				status = "disabled";
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x25.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x25.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x25.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x25.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -10,7 +10,7 @@
 
 / {
 	model = "Atmel AT91SAM9X25 SoC";
-	compatible = "atmel, at91sam9x25, atmel,at91sam9x5";
+	compatible = "atmel,at91sam9x25", "atmel,at91sam9x5";
 
 	ahb {
 		apb {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x35.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x35.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x35.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x35.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -10,7 +10,7 @@
 
 / {
 	model = "Atmel AT91SAM9X35 SoC";
-	compatible = "atmel, at91sam9x35, atmel,at91sam9x5";
+	compatible = "atmel,at91sam9x35", "atmel,at91sam9x5";
 
 	ahb {
 		apb {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x5.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x5.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x5.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x5.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -402,8 +402,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf801c000 0x200>;
 				interrupts = <5 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
@@ -413,8 +411,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8020000 0x200>;
 				interrupts = <6 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
@@ -424,8 +420,6 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8024000 0x200>;
 				interrupts = <7 4 5>;
-				atmel,use-dma-rx;
-				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x5ek.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x5ek.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/at91sam9x5ek.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/at91sam9x5ek.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -13,7 +13,7 @@
 	compatible = "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
 
 	chosen {
-		bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+		bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
 	};
 
 	ahb {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dns320.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dns320.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dns320.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dns320.dts	2013-05-11 16:57:46.000000000 -0400
@@ -42,12 +42,10 @@
 
 	ocp@f1000000 {
 		serial@12000 {
-			clock-frequency = <166666667>;
 			status = "okay";
 		};
 
 		serial@12100 {
-			clock-frequency = <166666667>;
 			status = "okay";
 		};
 	};
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dns325.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dns325.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dns325.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dns325.dts	2013-05-11 16:57:46.000000000 -0400
@@ -50,7 +50,6 @@
 			};
 		};
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "okay";
 		};
 	};
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dockstar.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dockstar.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dockstar.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dockstar.dts	2013-05-11 16:57:46.000000000 -0400
@@ -37,7 +37,6 @@
 			};
 		};
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dreamplug.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dreamplug.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-dreamplug.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-dreamplug.dts	2013-05-11 16:57:46.000000000 -0400
@@ -38,7 +38,6 @@
 			};
 		};
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -38,6 +38,7 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			interrupts = <35>, <36>, <37>, <38>;
+			clocks = <&gate_clk 7>;
 		};
 
 		gpio1: gpio@10140 {
@@ -49,6 +50,7 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			interrupts = <39>, <40>, <41>;
+			clocks = <&gate_clk 7>;
 		};
 
 		serial@12000 {
@@ -57,7 +59,6 @@
 			reg-shift = <2>;
 			interrupts = <33>;
 			clocks = <&gate_clk 7>;
-			/* set clock-frequency in board dts */
 			status = "disabled";
 		};
 
@@ -67,7 +68,6 @@
 			reg-shift = <2>;
 			interrupts = <34>;
 			clocks = <&gate_clk 7>;
-			/* set clock-frequency in board dts */
 			status = "disabled";
 		};
 
@@ -75,6 +75,7 @@
 			compatible = "marvell,kirkwood-rtc", "marvell,orion-rtc";
 			reg = <0x10300 0x20>;
 			interrupts = <53>;
+			clocks = <&gate_clk 7>;
 		};
 
 		spi@10600 {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-goflexnet.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-goflexnet.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-goflexnet.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-goflexnet.dts	2013-05-11 16:57:46.000000000 -0400
@@ -73,11 +73,11 @@
 			};
 		};
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
 		nand@3000000 {
+			chip-delay = <40>;
 			status = "okay";
 
 			partition@0 {
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-ib62x0.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-ib62x0.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-ib62x0.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-ib62x0.dts	2013-05-11 16:57:46.000000000 -0400
@@ -51,7 +51,6 @@
 			};
 		};
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "okay";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-iconnect.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-iconnect.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-iconnect.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-iconnect.dts	2013-05-11 16:57:46.000000000 -0400
@@ -78,7 +78,6 @@
 			};
 		};
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts	2013-05-11 16:57:46.000000000 -0400
@@ -96,11 +96,11 @@
 				marvell,function = "gpio";
 			};
 			pmx_led_rebuild_brt_ctrl_1: pmx-led-rebuild-brt-ctrl-1 {
-				marvell,pins = "mpp44";
+				marvell,pins = "mpp46";
 				marvell,function = "gpio";
 			};
 			pmx_led_rebuild_brt_ctrl_2: pmx-led-rebuild-brt-ctrl-2 {
-				marvell,pins = "mpp45";
+				marvell,pins = "mpp47";
 				marvell,function = "gpio";
 			};
 
@@ -115,7 +115,6 @@
 		};
 
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
@@ -158,14 +157,14 @@
 			gpios = <&gpio0 16 0>;
 			linux,default-trigger = "default-on";
 		};
-		health_led1 {
+		rebuild_led {
+			label = "status:white:rebuild_led";
+			gpios = <&gpio1 4 0>;
+		};
+		health_led {
 			label = "status:red:health_led";
 			gpios = <&gpio1 5 0>;
 		};
-		health_led2 {
-			label = "status:white:health_led";
-			gpios = <&gpio1 4 0>;
-		};
 		backup_led {
 			label = "status:blue:backup_led";
 			gpios = <&gpio0 15 0>;
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-km_kirkwood.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-km_kirkwood.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-km_kirkwood.dts	2013-05-11 16:57:46.000000000 -0400
@@ -34,7 +34,6 @@
 		};
 
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-lschlv2.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-lschlv2.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-lschlv2.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-lschlv2.dts	2013-05-11 16:57:46.000000000 -0400
@@ -13,7 +13,6 @@
 
 	ocp@f1000000 {
 		serial@12000 {
-			clock-frequency = <166666667>;
 			status = "okay";
 		};
 	};
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-lsxhl.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-lsxhl.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-lsxhl.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-lsxhl.dts	2013-05-11 16:57:46.000000000 -0400
@@ -13,7 +13,6 @@
 
 	ocp@f1000000 {
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "okay";
 		};
 	};
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-mplcec4.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-mplcec4.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-mplcec4.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-mplcec4.dts	2013-05-11 16:57:46.000000000 -0400
@@ -91,7 +91,6 @@
                 };
 
                 serial@12000 {
-                        clock-frequency = <200000000>;
                         status = "ok";
                 };
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-ns2-common.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-ns2-common.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-ns2-common.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -23,7 +23,6 @@
 		};
 
 		serial@12000 {
-			clock-frequency = <166666667>;
 			status = "okay";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-nsa310.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-nsa310.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-nsa310.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-nsa310.dts	2013-05-11 16:57:46.000000000 -0400
@@ -18,7 +18,6 @@
 	ocp@f1000000 {
 
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-openblocks_a6.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-openblocks_a6.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-openblocks_a6.dts	2013-05-11 16:57:46.000000000 -0400
@@ -18,12 +18,10 @@
 
 	ocp@f1000000 {
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
 		serial@12100 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-topkick.dts linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-topkick.dts
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/kirkwood-topkick.dts	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/kirkwood-topkick.dts	2013-05-11 16:57:46.000000000 -0400
@@ -17,7 +17,6 @@
 
 	ocp@f1000000 {
 		serial@12000 {
-			clock-frequency = <200000000>;
 			status = "ok";
 		};
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/tegra20.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/tegra20.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/tegra20.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/tegra20.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -314,7 +314,7 @@
 
 	spi@7000d800 {
 		compatible = "nvidia,tegra20-slink";
-		reg = <0x7000d480 0x200>;
+		reg = <0x7000d800 0x200>;
 		interrupts = <0 83 0x04>;
 		nvidia,dma-request-selector = <&apbdma 17>;
 		#address-cells = <1>;
diff -druNp linux-libre-3.8-gnu1/arch/arm/boot/dts/tegra30.dtsi linux-libre-3.8.13-gnu1/arch/arm/boot/dts/tegra30.dtsi
--- linux-libre-3.8-gnu1/arch/arm/boot/dts/tegra30.dtsi	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/boot/dts/tegra30.dtsi	2013-05-11 16:57:46.000000000 -0400
@@ -309,7 +309,7 @@
 
 	spi@7000d800 {
 		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
-		reg = <0x7000d480 0x200>;
+		reg = <0x7000d800 0x200>;
 		interrupts = <0 83 0x04>;
 		nvidia,dma-request-selector = <&apbdma 17>;
 		#address-cells = <1>;
diff -druNp linux-libre-3.8-gnu1/arch/arm/configs/at91sam9g45_defconfig linux-libre-3.8.13-gnu1/arch/arm/configs/at91sam9g45_defconfig
--- linux-libre-3.8-gnu1/arch/arm/configs/at91sam9g45_defconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/configs/at91sam9g45_defconfig	2013-05-11 16:57:46.000000000 -0400
@@ -173,7 +173,6 @@ CONFIG_MMC=y
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_SDIO_UART=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_ATMELMCI_DMA=y
 CONFIG_LEDS_ATMEL_PWM=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGER_TIMER=y
diff -druNp linux-libre-3.8-gnu1/arch/arm/configs/mxs_defconfig linux-libre-3.8.13-gnu1/arch/arm/configs/mxs_defconfig
--- linux-libre-3.8-gnu1/arch/arm/configs/mxs_defconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/configs/mxs_defconfig	2013-05-11 16:57:46.000000000 -0400
@@ -118,6 +118,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_LOGO=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_STORAGE=y
diff -druNp linux-libre-3.8-gnu1/arch/arm/include/asm/delay.h linux-libre-3.8.13-gnu1/arch/arm/include/asm/delay.h
--- linux-libre-3.8-gnu1/arch/arm/include/asm/delay.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/include/asm/delay.h	2013-05-11 16:57:46.000000000 -0400
@@ -24,6 +24,7 @@ extern struct arm_delay_ops {
 	void (*delay)(unsigned long);
 	void (*const_udelay)(unsigned long);
 	void (*udelay)(unsigned long);
+	bool const_clock;
 } arm_delay_ops;
 
 #define __delay(n)		arm_delay_ops.delay(n)
diff -druNp linux-libre-3.8-gnu1/arch/arm/include/asm/hardware/iop3xx.h linux-libre-3.8.13-gnu1/arch/arm/include/asm/hardware/iop3xx.h
--- linux-libre-3.8-gnu1/arch/arm/include/asm/hardware/iop3xx.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/include/asm/hardware/iop3xx.h	2013-05-11 16:57:46.000000000 -0400
@@ -37,7 +37,7 @@ extern int iop3xx_get_init_atu(void);
  * IOP3XX processor registers
  */
 #define IOP3XX_PERIPHERAL_PHYS_BASE	0xffffe000
-#define IOP3XX_PERIPHERAL_VIRT_BASE	0xfeffe000
+#define IOP3XX_PERIPHERAL_VIRT_BASE	0xfedfe000
 #define IOP3XX_PERIPHERAL_SIZE		0x00002000
 #define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
 					IOP3XX_PERIPHERAL_SIZE - 1)
diff -druNp linux-libre-3.8-gnu1/arch/arm/include/asm/mmu_context.h linux-libre-3.8.13-gnu1/arch/arm/include/asm/mmu_context.h
--- linux-libre-3.8-gnu1/arch/arm/include/asm/mmu_context.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/include/asm/mmu_context.h	2013-05-11 16:57:46.000000000 -0400
@@ -25,7 +25,7 @@ void __check_vmalloc_seq(struct mm_struc
 #ifdef CONFIG_CPU_HAS_ASID
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
-#define init_new_context(tsk,mm)	({ mm->context.id = 0; })
+#define init_new_context(tsk,mm)	({ atomic64_set(&mm->context.id, 0); 0; })
 
 #else	/* !CONFIG_CPU_HAS_ASID */
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/include/asm/mmu.h linux-libre-3.8.13-gnu1/arch/arm/include/asm/mmu.h
--- linux-libre-3.8-gnu1/arch/arm/include/asm/mmu.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/include/asm/mmu.h	2013-05-11 16:57:46.000000000 -0400
@@ -5,15 +5,15 @@
 
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
-	u64 id;
+	atomic64_t	id;
 #endif
-	unsigned int vmalloc_seq;
+	unsigned int	vmalloc_seq;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
 #define ASID_BITS	8
 #define ASID_MASK	((~0ULL) << ASID_BITS)
-#define ASID(mm)	((mm)->context.id & ~ASID_MASK)
+#define ASID(mm)	((mm)->context.id.counter & ~ASID_MASK)
 #else
 #define ASID(mm)	(0)
 #endif
@@ -26,7 +26,7 @@ typedef struct {
  *  modified for 2.6 by Hyok S. Choi <hyok.choi@samsung.com>
  */
 typedef struct {
-	unsigned long		end_brk;
+	unsigned long	end_brk;
 } mm_context_t;
 
 #endif
diff -druNp linux-libre-3.8-gnu1/arch/arm/include/asm/pgtable.h linux-libre-3.8.13-gnu1/arch/arm/include/asm/pgtable.h
--- linux-libre-3.8-gnu1/arch/arm/include/asm/pgtable.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/include/asm/pgtable.h	2013-05-11 16:57:46.000000000 -0400
@@ -61,6 +61,15 @@ extern void __pgd_error(const char *file
 #define FIRST_USER_ADDRESS	PAGE_SIZE
 
 /*
+ * Use TASK_SIZE as the ceiling argument for free_pgtables() and
+ * free_pgd_range() to avoid freeing the modules pmd when LPAE is enabled (pmd
+ * page shared between user and kernel).
+ */
+#ifdef CONFIG_ARM_LPAE
+#define USER_PGTABLES_CEILING	TASK_SIZE
+#endif
+
+/*
  * The pgprot_* and protection_map entries will be fixed up in runtime
  * to include the cachable and bufferable bits based on memory policy,
  * as well as any architecture dependent bits like global/ASID and SMP
@@ -240,7 +249,8 @@ static inline pte_t pte_mkspecial(pte_t
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER | L_PTE_NONE;
+	const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER |
+		L_PTE_NONE | L_PTE_VALID;
 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
 	return pte;
 }
diff -druNp linux-libre-3.8-gnu1/arch/arm/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/arm/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/arm/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -29,6 +29,7 @@ struct sigaction {
 	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/arm/kernel/asm-offsets.c linux-libre-3.8.13-gnu1/arch/arm/kernel/asm-offsets.c
--- linux-libre-3.8-gnu1/arch/arm/kernel/asm-offsets.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/kernel/asm-offsets.c	2013-05-11 16:57:46.000000000 -0400
@@ -107,7 +107,7 @@ int main(void)
   BLANK();
 #endif
 #ifdef CONFIG_CPU_HAS_ASID
-  DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
+  DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id.counter));
   BLANK();
 #endif
   DEFINE(VMA_VM_MM,		offsetof(struct vm_area_struct, vm_mm));
diff -druNp linux-libre-3.8-gnu1/arch/arm/kernel/head.S linux-libre-3.8.13-gnu1/arch/arm/kernel/head.S
--- linux-libre-3.8-gnu1/arch/arm/kernel/head.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/kernel/head.S	2013-05-11 16:57:46.000000000 -0400
@@ -184,13 +184,22 @@ __create_page_tables:
 	orr	r3, r3, #3			@ PGD block type
 	mov	r6, #4				@ PTRS_PER_PGD
 	mov	r7, #1 << (55 - 32)		@ L_PGD_SWAPPER
-1:	str	r3, [r0], #4			@ set bottom PGD entry bits
+1:
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	str	r7, [r0], #4			@ set top PGD entry bits
+	str	r3, [r0], #4			@ set bottom PGD entry bits
+#else
+	str	r3, [r0], #4			@ set bottom PGD entry bits
 	str	r7, [r0], #4			@ set top PGD entry bits
+#endif
 	add	r3, r3, #0x1000			@ next PMD table
 	subs	r6, r6, #1
 	bne	1b
 
 	add	r4, r4, #0x1000			@ point to the PMD tables
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	add	r4, r4, #4			@ we only write the bottom word
+#endif
 #endif
 
 	ldr	r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
@@ -258,6 +267,11 @@ __create_page_tables:
 	addne	r6, r6, #1 << SECTION_SHIFT
 	strne	r6, [r3]
 
+#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
+	sub	r4, r4, #4			@ Fixup page table pointer
+						@ for 64-bit descriptors
+#endif
+
 #ifdef CONFIG_DEBUG_LL
 #if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
 	/*
@@ -276,13 +290,17 @@ __create_page_tables:
 	orr	r3, r7, r3, lsl #SECTION_SHIFT
 #ifdef CONFIG_ARM_LPAE
 	mov	r7, #1 << (54 - 32)		@ XN
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	str	r7, [r0], #4
+	str	r3, [r0], #4
 #else
-	orr	r3, r3, #PMD_SECT_XN
-#endif
 	str	r3, [r0], #4
-#ifdef CONFIG_ARM_LPAE
 	str	r7, [r0], #4
 #endif
+#else
+	orr	r3, r3, #PMD_SECT_XN
+	str	r3, [r0], #4
+#endif
 
 #else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */
 	/* we don't need any serial debugging mappings */
diff -druNp linux-libre-3.8-gnu1/arch/arm/kernel/perf_event.c linux-libre-3.8.13-gnu1/arch/arm/kernel/perf_event.c
--- linux-libre-3.8-gnu1/arch/arm/kernel/perf_event.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/kernel/perf_event.c	2013-05-11 16:57:46.000000000 -0400
@@ -261,7 +261,10 @@ validate_event(struct pmu_hw_events *hw_
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct pmu *leader_pmu = event->group_leader->pmu;
 
-	if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
+	if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
+		return 1;
+
+	if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
 		return 1;
 
 	return armpmu->get_event_idx(hw_events, event) >= 0;
diff -druNp linux-libre-3.8-gnu1/arch/arm/kernel/perf_event_v7.c linux-libre-3.8.13-gnu1/arch/arm/kernel/perf_event_v7.c
--- linux-libre-3.8-gnu1/arch/arm/kernel/perf_event_v7.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/kernel/perf_event_v7.c	2013-05-11 16:57:46.000000000 -0400
@@ -774,7 +774,7 @@ static const unsigned armv7_a7_perf_cach
 /*
  * PMXEVTYPER: Event selection reg
  */
-#define	ARMV7_EVTYPE_MASK	0xc00000ff	/* Mask for writable bits */
+#define	ARMV7_EVTYPE_MASK	0xc80000ff	/* Mask for writable bits */
 #define	ARMV7_EVTYPE_EVENT	0xff		/* Mask for EVENT bits */
 
 /*
diff -druNp linux-libre-3.8-gnu1/arch/arm/kernel/sched_clock.c linux-libre-3.8.13-gnu1/arch/arm/kernel/sched_clock.c
--- linux-libre-3.8-gnu1/arch/arm/kernel/sched_clock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/kernel/sched_clock.c	2013-05-11 16:57:46.000000000 -0400
@@ -45,12 +45,12 @@ static u32 notrace jiffy_sched_clock_rea
 
 static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
 
-static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 {
 	return (cyc * mult) >> shift;
 }
 
-static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask)
+static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask)
 {
 	u64 epoch_ns;
 	u32 epoch_cyc;
@@ -93,11 +93,11 @@ static void notrace update_sched_clock(v
 	 * detectable in cyc_to_fixed_sched_clock().
 	 */
 	raw_local_irq_save(flags);
-	cd.epoch_cyc = cyc;
+	cd.epoch_cyc_copy = cyc;
 	smp_wmb();
 	cd.epoch_ns = ns;
 	smp_wmb();
-	cd.epoch_cyc_copy = cyc;
+	cd.epoch_cyc = cyc;
 	raw_local_irq_restore(flags);
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/kernel/smp.c linux-libre-3.8.13-gnu1/arch/arm/kernel/smp.c
--- linux-libre-3.8-gnu1/arch/arm/kernel/smp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/kernel/smp.c	2013-05-11 16:57:46.000000000 -0400
@@ -693,6 +693,9 @@ static int cpufreq_callback(struct notif
 	if (freq->flags & CPUFREQ_CONST_LOOPS)
 		return NOTIFY_OK;
 
+	if (arm_delay_ops.const_clock)
+		return NOTIFY_OK;
+
 	if (!per_cpu(l_p_j_ref, cpu)) {
 		per_cpu(l_p_j_ref, cpu) =
 			per_cpu(cpu_data, cpu).loops_per_jiffy;
diff -druNp linux-libre-3.8-gnu1/arch/arm/lib/delay.c linux-libre-3.8.13-gnu1/arch/arm/lib/delay.c
--- linux-libre-3.8-gnu1/arch/arm/lib/delay.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/lib/delay.c	2013-05-11 16:57:46.000000000 -0400
@@ -77,6 +77,7 @@ void __init register_current_timer_delay
 		arm_delay_ops.delay		= __timer_delay;
 		arm_delay_ops.const_udelay	= __timer_const_udelay;
 		arm_delay_ops.udelay		= __timer_udelay;
+		arm_delay_ops.const_clock	= true;
 		delay_calibrated		= true;
 	} else {
 		pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-at91/board-foxg20.c linux-libre-3.8.13-gnu1/arch/arm/mach-at91/board-foxg20.c
--- linux-libre-3.8-gnu1/arch/arm/mach-at91/board-foxg20.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-at91/board-foxg20.c	2013-05-11 16:57:46.000000000 -0400
@@ -176,6 +176,7 @@ static struct w1_gpio_platform_data w1_g
 	/* If you choose to use a pin other than PB16 it needs to be 3.3V */
 	.pin		= AT91_PIN_PB16,
 	.is_open_drain  = 1,
+	.ext_pullup_enable_pin	= -EINVAL,
 };
 
 static struct platform_device w1_device = {
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-at91/board-stamp9g20.c linux-libre-3.8.13-gnu1/arch/arm/mach-at91/board-stamp9g20.c
--- linux-libre-3.8-gnu1/arch/arm/mach-at91/board-stamp9g20.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-at91/board-stamp9g20.c	2013-05-11 16:57:46.000000000 -0400
@@ -188,6 +188,7 @@ static struct spi_board_info portuxg20_s
 static struct w1_gpio_platform_data w1_gpio_pdata = {
 	.pin		= AT91_PIN_PA29,
 	.is_open_drain	= 1,
+	.ext_pullup_enable_pin	= -EINVAL,
 };
 
 static struct platform_device w1_device = {
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-at91/setup.c linux-libre-3.8.13-gnu1/arch/arm/mach-at91/setup.c
--- linux-libre-3.8-gnu1/arch/arm/mach-at91/setup.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-at91/setup.c	2013-05-11 16:57:46.000000000 -0400
@@ -333,7 +333,7 @@ static void at91_dt_rstc(void)
 
 	of_id = of_match_node(rstc_ids, np);
 	if (!of_id)
-		panic("AT91: rtsc no restart function availlable\n");
+		panic("AT91: rtsc no restart function available\n");
 
 	arm_pm_restart = of_id->data;
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-cns3xxx/core.c linux-libre-3.8.13-gnu1/arch/arm/mach-cns3xxx/core.c
--- linux-libre-3.8-gnu1/arch/arm/mach-cns3xxx/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-cns3xxx/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -22,19 +22,9 @@
 
 static struct map_desc cns3xxx_io_desc[] __initdata = {
 	{
-		.virtual	= CNS3XXX_TC11MP_TWD_BASE_VIRT,
-		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT,
-		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT,
-		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE),
-		.length		= SZ_4K,
+		.virtual	= CNS3XXX_TC11MP_SCU_BASE_VIRT,
+		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
+		.length		= SZ_8K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= CNS3XXX_TIMER1_2_3_BASE_VIRT,
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h linux-libre-3.8.13-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
--- linux-libre-3.8-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h	2013-05-11 16:57:46.000000000 -0400
@@ -94,10 +94,10 @@
 #define RTC_INTR_STS_OFFSET			0x34
 
 #define CNS3XXX_MISC_BASE			0x76000000	/* Misc Control */
-#define CNS3XXX_MISC_BASE_VIRT			0xFFF07000	/* Misc Control */
+#define CNS3XXX_MISC_BASE_VIRT			0xFB000000	/* Misc Control */
 
 #define CNS3XXX_PM_BASE				0x77000000	/* Power Management Control */
-#define CNS3XXX_PM_BASE_VIRT			0xFFF08000
+#define CNS3XXX_PM_BASE_VIRT			0xFB001000
 
 #define PM_CLK_GATE_OFFSET			0x00
 #define PM_SOFT_RST_OFFSET			0x04
@@ -109,7 +109,7 @@
 #define PM_PLL_HM_PD_OFFSET			0x1C
 
 #define CNS3XXX_UART0_BASE			0x78000000	/* UART 0 */
-#define CNS3XXX_UART0_BASE_VIRT			0xFFF09000
+#define CNS3XXX_UART0_BASE_VIRT			0xFB002000
 
 #define CNS3XXX_UART1_BASE			0x78400000	/* UART 1 */
 #define CNS3XXX_UART1_BASE_VIRT			0xFFF0A000
@@ -130,7 +130,7 @@
 #define CNS3XXX_I2S_BASE_VIRT			0xFFF10000
 
 #define CNS3XXX_TIMER1_2_3_BASE			0x7C800000	/* Timer */
-#define CNS3XXX_TIMER1_2_3_BASE_VIRT		0xFFF10800
+#define CNS3XXX_TIMER1_2_3_BASE_VIRT		0xFB003000
 
 #define TIMER1_COUNTER_OFFSET			0x00
 #define TIMER1_AUTO_RELOAD_OFFSET		0x04
@@ -227,16 +227,16 @@
  * Testchip peripheral and fpga gic regions
  */
 #define CNS3XXX_TC11MP_SCU_BASE			0x90000000	/* IRQ, Test chip */
-#define CNS3XXX_TC11MP_SCU_BASE_VIRT		0xFF000000
+#define CNS3XXX_TC11MP_SCU_BASE_VIRT		0xFB004000
 
 #define CNS3XXX_TC11MP_GIC_CPU_BASE		0x90000100	/* Test chip interrupt controller CPU interface */
-#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT	0xFF000100
+#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT	(CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100)
 
 #define CNS3XXX_TC11MP_TWD_BASE			0x90000600
-#define CNS3XXX_TC11MP_TWD_BASE_VIRT		0xFF000600
+#define CNS3XXX_TC11MP_TWD_BASE_VIRT		(CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600)
 
 #define CNS3XXX_TC11MP_GIC_DIST_BASE		0x90001000	/* Test chip interrupt controller distributor */
-#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT	0xFF001000
+#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT	(CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000)
 
 #define CNS3XXX_TC11MP_L220_BASE		0x92002000	/* L220 registers */
 #define CNS3XXX_TC11MP_L220_BASE_VIRT		0xFF002000
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-davinci/dma.c linux-libre-3.8.13-gnu1/arch/arm/mach-davinci/dma.c
--- linux-libre-3.8-gnu1/arch/arm/mach-davinci/dma.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-davinci/dma.c	2013-05-11 16:57:46.000000000 -0400
@@ -743,6 +743,9 @@ EXPORT_SYMBOL(edma_free_channel);
  */
 int edma_alloc_slot(unsigned ctlr, int slot)
 {
+	if (!edma_cc[ctlr])
+		return -EINVAL;
+
 	if (slot >= 0)
 		slot = EDMA_CHAN_SLOT(slot);
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-exynos/common.c linux-libre-3.8.13-gnu1/arch/arm/mach-exynos/common.c
--- linux-libre-3.8-gnu1/arch/arm/mach-exynos/common.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-exynos/common.c	2013-05-11 16:57:46.000000000 -0400
@@ -299,6 +299,7 @@ void exynos4_restart(char mode, const ch
 
 void exynos5_restart(char mode, const char *cmd)
 {
+	struct device_node *np;
 	u32 val;
 	void __iomem *addr;
 
@@ -306,8 +307,9 @@ void exynos5_restart(char mode, const ch
 		val = 0x1;
 		addr = EXYNOS_SWRESET;
 	} else if (of_machine_is_compatible("samsung,exynos5440")) {
-		val = (0x10 << 20) | (0x1 << 16);
-		addr = EXYNOS5440_SWRESET;
+		np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
+		addr = of_iomap(np, 0) + 0xcc;
+		val = (0xfff << 20) | (0x1 << 16);
 	} else {
 		pr_err("%s: cannot support non-DT\n", __func__);
 		return;
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-imx/clk-imx25.c linux-libre-3.8.13-gnu1/arch/arm/mach-imx/clk-imx25.c
--- linux-libre-3.8-gnu1/arch/arm/mach-imx/clk-imx25.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-imx/clk-imx25.c	2013-05-11 16:57:46.000000000 -0400
@@ -224,6 +224,9 @@ static int __init __mx25_clocks_init(uns
 
 	clk_prepare_enable(clk[emi_ahb]);
 
+	/* Clock source for gpt must be derived from AHB */
+	clk_set_parent(clk[per5_sel], clk[ahb]);
+
 	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-imx/clk-imx35.c linux-libre-3.8.13-gnu1/arch/arm/mach-imx/clk-imx35.c
--- linux-libre-3.8-gnu1/arch/arm/mach-imx/clk-imx35.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-imx/clk-imx35.c	2013-05-11 16:57:46.000000000 -0400
@@ -257,6 +257,7 @@ int __init mx35_clocks_init()
 	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
 	clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
 	clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
+	clk_register_clkdev(clk[admux_gate], "audmux", NULL);
 
 	clk_prepare_enable(clk[spba_gate]);
 	clk_prepare_enable(clk[gpio1_gate]);
@@ -264,6 +265,8 @@ int __init mx35_clocks_init()
 	clk_prepare_enable(clk[gpio3_gate]);
 	clk_prepare_enable(clk[iim_gate]);
 	clk_prepare_enable(clk[emi_gate]);
+	clk_prepare_enable(clk[max_gate]);
+	clk_prepare_enable(clk[iomuxc_gate]);
 
 	/*
 	 * SCC is needed to boot via mmc after a watchdog reset. The clock code
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-imx/common.h linux-libre-3.8.13-gnu1/arch/arm/mach-imx/common.h
--- linux-libre-3.8-gnu1/arch/arm/mach-imx/common.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-imx/common.h	2013-05-11 16:57:46.000000000 -0400
@@ -116,6 +116,8 @@ void tzic_handle_irq(struct pt_regs *);
 
 extern void imx_enable_cpu(int cpu, bool enable);
 extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern u32 imx_get_cpu_arg(int cpu);
+extern void imx_set_cpu_arg(int cpu, u32 arg);
 #ifdef CONFIG_DEBUG_LL
 extern void imx_lluart_map_io(void);
 #else
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-imx/hotplug.c linux-libre-3.8.13-gnu1/arch/arm/mach-imx/hotplug.c
--- linux-libre-3.8-gnu1/arch/arm/mach-imx/hotplug.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-imx/hotplug.c	2013-05-11 16:57:46.000000000 -0400
@@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(vo
 void imx_cpu_die(unsigned int cpu)
 {
 	cpu_enter_lowpower();
+	/*
+	 * We use the cpu jumping argument register to sync with
+	 * imx_cpu_kill() which is running on cpu0 and waiting for
+	 * the register being cleared to kill the cpu.
+	 */
+	imx_set_cpu_arg(cpu, ~0);
 	cpu_do_idle();
 }
 
 int imx_cpu_kill(unsigned int cpu)
 {
+	unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+	while (imx_get_cpu_arg(cpu) == 0)
+		if (time_after(jiffies, timeout))
+			return 0;
 	imx_enable_cpu(cpu, false);
+	imx_set_cpu_arg(cpu, 0);
 	return 1;
 }
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-imx/src.c linux-libre-3.8.13-gnu1/arch/arm/mach-imx/src.c
--- linux-libre-3.8-gnu1/arch/arm/mach-imx/src.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-imx/src.c	2013-05-11 16:57:46.000000000 -0400
@@ -43,6 +43,18 @@ void imx_set_cpu_jump(int cpu, void *jum
 		       src_base + SRC_GPR1 + cpu * 8);
 }
 
+u32 imx_get_cpu_arg(int cpu)
+{
+	cpu = cpu_logical_map(cpu);
+	return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
+void imx_set_cpu_arg(int cpu, u32 arg)
+{
+	cpu = cpu_logical_map(cpu);
+	writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
 void imx_src_prepare_restart(void)
 {
 	u32 val;
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-integrator/integrator_ap.c linux-libre-3.8.13-gnu1/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-3.8-gnu1/arch/arm/mach-integrator/integrator_ap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-integrator/integrator_ap.c	2013-05-11 16:57:46.000000000 -0400
@@ -613,7 +613,6 @@ static struct map_desc ap_io_desc_atag[]
 static void __init ap_map_io_atag(void)
 {
 	iotable_init(ap_io_desc_atag, ARRAY_SIZE(ap_io_desc_atag));
-	ap_syscon_base = __io_address(INTEGRATOR_SC_BASE);
 	ap_map_io();
 }
 
@@ -685,6 +684,7 @@ static void __init ap_init(void)
 
 	platform_device_register(&cfi_flash_device);
 
+	ap_syscon_base = __io_address(INTEGRATOR_SC_BASE);
 	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
 		struct lm_device *lmdev;
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c linux-libre-3.8.13-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c
--- linux-libre-3.8-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-ixp4xx/vulcan-setup.c	2013-05-11 16:57:46.000000000 -0400
@@ -163,6 +163,7 @@ static struct platform_device vulcan_max
 
 static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = {
 	.pin			= 14,
+	.ext_pullup_enable_pin	= -EINVAL,
 };
 
 static struct platform_device vulcan_w1_gpio = {
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-kirkwood/board-dt.c linux-libre-3.8.13-gnu1/arch/arm/mach-kirkwood/board-dt.c
--- linux-libre-3.8-gnu1/arch/arm/mach-kirkwood/board-dt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-kirkwood/board-dt.c	2013-05-11 16:57:46.000000000 -0400
@@ -41,16 +41,12 @@ static void __init kirkwood_legacy_clk_i
 
 	struct device_node *np = of_find_compatible_node(
 		NULL, NULL, "marvell,kirkwood-gating-clock");
-
 	struct of_phandle_args clkspec;
+	struct clk *clk;
 
 	clkspec.np = np;
 	clkspec.args_count = 1;
 
-	clkspec.args[0] = CGC_BIT_GE0;
-	orion_clkdev_add(NULL, "mv643xx_eth_port.0",
-			 of_clk_get_from_provider(&clkspec));
-
 	clkspec.args[0] = CGC_BIT_PEX0;
 	orion_clkdev_add("0", "pcie",
 			 of_clk_get_from_provider(&clkspec));
@@ -63,14 +59,24 @@ static void __init kirkwood_legacy_clk_i
 	orion_clkdev_add("1", "pcie",
 			 of_clk_get_from_provider(&clkspec));
 
-	clkspec.args[0] = CGC_BIT_GE1;
-	orion_clkdev_add(NULL, "mv643xx_eth_port.1",
-			 of_clk_get_from_provider(&clkspec));
-
 	clkspec.args[0] = CGC_BIT_SDIO;
 	orion_clkdev_add(NULL, "mvsdio",
 			 of_clk_get_from_provider(&clkspec));
 
+	/*
+	 * The ethernet interfaces forget the MAC address assigned by
+	 * u-boot if the clocks are turned off. Until proper DT support
+	 * is available we always enable them for now.
+	 */
+	clkspec.args[0] = CGC_BIT_GE0;
+	clk = of_clk_get_from_provider(&clkspec);
+	orion_clkdev_add(NULL, "mv643xx_eth_port.0", clk);
+	clk_prepare_enable(clk);
+
+	clkspec.args[0] = CGC_BIT_GE1;
+	clk = of_clk_get_from_provider(&clkspec);
+	orion_clkdev_add(NULL, "mv643xx_eth_port.1", clk);
+	clk_prepare_enable(clk);
 }
 
 static void __init kirkwood_of_clk_init(void)
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-omap2/common.h linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/common.h
--- linux-libre-3.8-gnu1/arch/arm/mach-omap2/common.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/common.h	2013-05-11 16:57:46.000000000 -0400
@@ -286,5 +286,8 @@ extern void omap_reserve(void);
 struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
+/* SoC specific clock initializer */
+extern int (*omap_clk_init)(void);
+
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-omap2/cpuidle34xx.c linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/cpuidle34xx.c
--- linux-libre-3.8-gnu1/arch/arm/mach-omap2/cpuidle34xx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/cpuidle34xx.c	2013-05-11 16:57:46.000000000 -0400
@@ -265,8 +265,9 @@ static int omap3_enter_idle_bm(struct cp
 static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
 
 static struct cpuidle_driver omap3_idle_driver = {
-	.name =		"omap3_idle",
-	.owner =	THIS_MODULE,
+	.name             = "omap3_idle",
+	.owner            = THIS_MODULE,
+	.en_core_tk_irqen = 1,
 	.states = {
 		{
 			.enter		  = omap3_enter_idle_bm,
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-omap2/io.c linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/io.c
--- linux-libre-3.8-gnu1/arch/arm/mach-omap2/io.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/io.c	2013-05-11 16:57:46.000000000 -0400
@@ -55,6 +55,12 @@
 #include "prm44xx.h"
 
 /*
+ * omap_clk_init: points to a function that does the SoC-specific
+ * clock initializations
+ */
+int (*omap_clk_init)(void);
+
+/*
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
  */
@@ -397,7 +403,7 @@ void __init omap2420_init_early(void)
 	omap242x_clockdomains_init();
 	omap2420_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap2420_clk_init();
+	omap_clk_init = omap2420_clk_init;
 }
 
 void __init omap2420_init_late(void)
@@ -427,7 +433,7 @@ void __init omap2430_init_early(void)
 	omap243x_clockdomains_init();
 	omap2430_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap2430_clk_init();
+	omap_clk_init = omap2430_clk_init;
 }
 
 void __init omap2430_init_late(void)
@@ -462,7 +468,7 @@ void __init omap3_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap3xxx_clk_init();
+	omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3430_init_early(void)
@@ -500,7 +506,7 @@ void __init ti81xx_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap3xxx_clk_init();
+	omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
@@ -568,7 +574,7 @@ void __init am33xx_init_early(void)
 	am33xx_clockdomains_init();
 	am33xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	am33xx_clk_init();
+	omap_clk_init = am33xx_clk_init;
 }
 #endif
 
@@ -593,7 +599,7 @@ void __init omap4430_init_early(void)
 	omap44xx_clockdomains_init();
 	omap44xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap4xxx_clk_init();
+	omap_clk_init = omap4xxx_clk_init;
 }
 
 void __init omap4430_init_late(void)
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-omap2/timer.c linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/timer.c
--- linux-libre-3.8-gnu1/arch/arm/mach-omap2/timer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-omap2/timer.c	2013-05-11 16:57:46.000000000 -0400
@@ -554,6 +554,8 @@ static inline void __init realtime_count
 			       clksrc_nr, clksrc_src)			\
 static void __init omap##name##_gptimer_timer_init(void)		\
 {									\
+	if (omap_clk_init)						\
+		omap_clk_init();					\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);	\
@@ -563,6 +565,8 @@ static void __init omap##name##_gptimer_
 				clksrc_nr, clksrc_src)			\
 static void __init omap##name##_sync32k_timer_init(void)		\
 {									\
+	if (omap_clk_init)						\
+		omap_clk_init();					\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	/* Enable the use of clocksource="gp_timer" kernel parameter */	\
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-pxa/include/mach/smemc.h linux-libre-3.8.13-gnu1/arch/arm/mach-pxa/include/mach/smemc.h
--- linux-libre-3.8-gnu1/arch/arm/mach-pxa/include/mach/smemc.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-pxa/include/mach/smemc.h	2013-05-11 16:57:46.000000000 -0400
@@ -37,6 +37,7 @@
 #define CSADRCFG1	(SMEMC_VIRT + 0x84)  /* Address Configuration Register for CS1 */
 #define CSADRCFG2	(SMEMC_VIRT + 0x88)  /* Address Configuration Register for CS2 */
 #define CSADRCFG3	(SMEMC_VIRT + 0x8C)  /* Address Configuration Register for CS3 */
+#define CSMSADRCFG	(SMEMC_VIRT + 0xA0)  /* Chip Select Configuration Register */
 
 /*
  * More handy macros for PCMCIA
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-pxa/raumfeld.c linux-libre-3.8.13-gnu1/arch/arm/mach-pxa/raumfeld.c
--- linux-libre-3.8-gnu1/arch/arm/mach-pxa/raumfeld.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-pxa/raumfeld.c	2013-05-11 16:57:46.000000000 -0400
@@ -505,6 +505,7 @@ static struct w1_gpio_platform_data w1_g
 	.pin			= GPIO_ONE_WIRE,
 	.is_open_drain		= 0,
 	.enable_external_pullup	= w1_enable_external_pullup,
+	.ext_pullup_enable_pin	= -EINVAL,
 };
 
 struct platform_device raumfeld_w1_gpio_device = {
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-pxa/smemc.c linux-libre-3.8.13-gnu1/arch/arm/mach-pxa/smemc.c
--- linux-libre-3.8-gnu1/arch/arm/mach-pxa/smemc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-pxa/smemc.c	2013-05-11 16:57:46.000000000 -0400
@@ -40,6 +40,8 @@ static void pxa3xx_smemc_resume(void)
 	__raw_writel(csadrcfg[1], CSADRCFG1);
 	__raw_writel(csadrcfg[2], CSADRCFG2);
 	__raw_writel(csadrcfg[3], CSADRCFG3);
+	/* CSMSADRCFG wakes up in its default state (0), so we need to set it */
+	__raw_writel(0x2, CSMSADRCFG);
 }
 
 static struct syscore_ops smemc_syscore_ops = {
@@ -49,8 +51,19 @@ static struct syscore_ops smemc_syscore_
 
 static int __init smemc_init(void)
 {
-	if (cpu_is_pxa3xx())
+	if (cpu_is_pxa3xx()) {
+		/*
+		 * The only documentation we have on the
+		 * Chip Select Configuration Register (CSMSADRCFG) is that
+		 * it must be programmed to 0x2.
+		 * Moreover, in the bit definitions, the second bit
+		 * (CSMSADRCFG[1]) is called "SETALWAYS".
+		 * Other bits are reserved in this register.
+		 */
+		__raw_writel(0x2, CSMSADRCFG);
+
 		register_syscore_ops(&smemc_syscore_ops);
+	}
 
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/include/mach/debug-macro.S linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/include/mach/debug-macro.S
--- linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/include/mach/debug-macro.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/include/mach/debug-macro.S	2013-05-11 16:57:46.000000000 -0400
@@ -40,17 +40,17 @@
 		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
 		addne	\rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
 		bic	\rd, \rd, #0xff000
-		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
+		ldr	\rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)]
 		and	\rd, \rd, #0x00ff0000
 		teq	\rd, #0x00440000		@ is it 2440?
 1004:
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		moveq	\rd, \rd, lsr #SHIFT_2440TXF
 		tst	\rd, #S3C2410_UFSTAT_TXFULL
 	.endm
 
 	.macro  fifo_full_s3c2410 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		tst	\rd, #S3C2410_UFSTAT_TXFULL
 	.endm
 
@@ -68,18 +68,18 @@
 		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
 		addne	\rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
 		bic	\rd, \rd, #0xff000
-		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
+		ldr	\rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)]
 		and	\rd, \rd, #0x00ff0000
 		teq	\rd, #0x00440000		@ is it 2440?
 
 10000:
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		andne	\rd, \rd, #S3C2410_UFSTAT_TXMASK
 		andeq	\rd, \rd, #S3C2440_UFSTAT_TXMASK
 	.endm
 
 	.macro fifo_level_s3c2410 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		and	\rd, \rd, #S3C2410_UFSTAT_TXMASK
 	.endm
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/include/mach/entry-macro.S linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/include/mach/entry-macro.S
--- linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/include/mach/entry-macro.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/include/mach/entry-macro.S	2013-05-11 16:57:46.000000000 -0400
@@ -31,10 +31,10 @@
 
 		@@ try the interrupt offset register, since it is there
 
-		ldr	\irqstat, [ \base, #INTPND ]
+		ldr	\irqstat, [\base, #INTPND ]
 		teq	\irqstat, #0
 		beq	1002f
-		ldr	\irqnr, [ \base, #INTOFFSET ]
+		ldr	\irqnr, [\base, #INTOFFSET ]
 		mov	\tmp, #1
 		tst	\irqstat, \tmp, lsl \irqnr
 		bne	1001f
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/pm-h1940.S linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/pm-h1940.S
--- linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/pm-h1940.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/pm-h1940.S	2013-05-11 16:57:46.000000000 -0400
@@ -30,4 +30,4 @@
 
 h1940_pm_return:
 	mov	r0, #S3C2410_PA_GPIO
-	ldr	pc, [ r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO ]
+	ldr	pc, [r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO]
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2410.S linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2410.S
--- linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2410.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2410.S	2013-05-11 16:57:46.000000000 -0400
@@ -45,9 +45,9 @@ ENTRY(s3c2410_cpu_suspend)
 	ldr	r4, =S3C2410_REFRESH
 	ldr	r5, =S3C24XX_MISCCR
 	ldr	r6, =S3C2410_CLKCON
-	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
-	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
-	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
+	ldr	r7, [r4]		@ get REFRESH (and ensure in TLB)
+	ldr	r8, [r5]		@ get MISCCR (and ensure in TLB)
+	ldr	r9, [r6]		@ get CLKCON (and ensure in TLB)
 
 	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
 	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
@@ -61,8 +61,8 @@ ENTRY(s3c2410_cpu_suspend)
 	@@ align next bit of code to cache line
 	.align	5
 s3c2410_do_sleep:
-	streq	r7, [ r4 ]			@ SDRAM sleep command
-	streq	r8, [ r5 ]			@ SDRAM power-down config
-	streq	r9, [ r6 ]			@ CPU sleep
+	streq	r7, [r4]			@ SDRAM sleep command
+	streq	r8, [r5]			@ SDRAM power-down config
+	streq	r9, [r6]			@ CPU sleep
 1:	beq	1b
 	mov	pc, r14
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2412.S linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2412.S
--- linux-libre-3.8-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2412.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-s3c24xx/sleep-s3c2412.S	2013-05-11 16:57:46.000000000 -0400
@@ -57,12 +57,12 @@ s3c2412_sleep_enter1:
 	 * retry, as simply returning causes the system to lock.
 	*/
 
-	ldrne	r9, [ r1 ]
-	strne	r9, [ r1 ]
-	ldrne	r9, [ r2 ]
-	strne	r9, [ r2 ]
-	ldrne	r9, [ r3 ]
-	strne	r9, [ r3 ]
+	ldrne	r9, [r1]
+	strne	r9, [r1]
+	ldrne	r9, [r2]
+	strne	r9, [r2]
+	ldrne	r9, [r3]
+	strne	r9, [r3]
 	bne	s3c2412_sleep_enter1
 
 	mov	pc, r14
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h linux-libre-3.8.13-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h
--- linux-libre-3.8-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h	2013-05-11 16:57:46.000000000 -0400
@@ -95,7 +95,7 @@
 #define U300_SPI_BASE			(U300_FAST_PER_PHYS_BASE+0x6000)
 
 /* Fast UART1 on U335 only */
-#define U300_UART1_BASE			(U300_SLOW_PER_PHYS_BASE+0x7000)
+#define U300_UART1_BASE			(U300_FAST_PER_PHYS_BASE+0x7000)
 
 /*
  * SLOW peripherals
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-versatile/core.c linux-libre-3.8.13-gnu1/arch/arm/mach-versatile/core.c
--- linux-libre-3.8-gnu1/arch/arm/mach-versatile/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-versatile/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/gfp.h>
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
+#include <linux/bitops.h>
 
 #include <asm/irq.h>
 #include <asm/hardware/arm_timer.h>
@@ -65,16 +66,28 @@
 #define VA_VIC_BASE		__io_address(VERSATILE_VIC_BASE)
 #define VA_SIC_BASE		__io_address(VERSATILE_SIC_BASE)
 
+/* These PIC IRQs are valid in each configuration */
+#define PIC_VALID_ALL	BIT(SIC_INT_KMI0) | BIT(SIC_INT_KMI1) | \
+			BIT(SIC_INT_SCI3) | BIT(SIC_INT_UART3) | \
+			BIT(SIC_INT_CLCD) | BIT(SIC_INT_TOUCH) | \
+			BIT(SIC_INT_KEYPAD) | BIT(SIC_INT_DoC) | \
+			BIT(SIC_INT_USB) | BIT(SIC_INT_PCI0) | \
+			BIT(SIC_INT_PCI1) | BIT(SIC_INT_PCI2) | \
+			BIT(SIC_INT_PCI3)
 #if 1
 #define IRQ_MMCI0A	IRQ_VICSOURCE22
 #define IRQ_AACI	IRQ_VICSOURCE24
 #define IRQ_ETH		IRQ_VICSOURCE25
 #define PIC_MASK	0xFFD00000
+#define PIC_VALID	PIC_VALID_ALL
 #else
 #define IRQ_MMCI0A	IRQ_SIC_MMCI0A
 #define IRQ_AACI	IRQ_SIC_AACI
 #define IRQ_ETH		IRQ_SIC_ETH
 #define PIC_MASK	0
+#define PIC_VALID	PIC_VALID_ALL | BIT(SIC_INT_MMCI0A) | \
+			BIT(SIC_INT_MMCI1A) | BIT(SIC_INT_AACI) | \
+			BIT(SIC_INT_ETH)
 #endif
 
 /* Lookup table for finding a DT node that represents the vic instance */
@@ -102,7 +115,7 @@ void __init versatile_init_irq(void)
 					      VERSATILE_SIC_BASE);
 
 	fpga_irq_init(VA_SIC_BASE, "SIC", IRQ_SIC_START,
-		IRQ_VICSOURCE31, ~PIC_MASK, np);
+		IRQ_VICSOURCE31, PIC_VALID, np);
 
 	/*
 	 * Interrupts on secondary controller from 0 to 8 are routed to
diff -druNp linux-libre-3.8-gnu1/arch/arm/mach-versatile/pci.c linux-libre-3.8.13-gnu1/arch/arm/mach-versatile/pci.c
--- linux-libre-3.8-gnu1/arch/arm/mach-versatile/pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mach-versatile/pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 
@@ -327,12 +328,12 @@ static int __init versatile_map_irq(cons
 	int irq;
 
 	/* slot,  pin,	irq
-	 *  24     1     27
-	 *  25     1     28
-	 *  26     1     29
-	 *  27     1     30
+	 *  24     1     IRQ_SIC_PCI0
+	 *  25     1     IRQ_SIC_PCI1
+	 *  26     1     IRQ_SIC_PCI2
+	 *  27     1     IRQ_SIC_PCI3
 	 */
-	irq = 27 + ((slot - 24 + pin - 1) & 3);
+	irq = IRQ_SIC_PCI0 + ((slot - 24 + pin - 1) & 3);
 
 	return irq;
 }
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/alignment.c linux-libre-3.8.13-gnu1/arch/arm/mm/alignment.c
--- linux-libre-3.8-gnu1/arch/arm/mm/alignment.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/alignment.c	2013-05-11 16:57:46.000000000 -0400
@@ -749,7 +749,6 @@ do_alignment(unsigned long addr, unsigne
 	unsigned long instr = 0, instrptr;
 	int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
 	unsigned int type;
-	mm_segment_t fs;
 	unsigned int fault;
 	u16 tinstr = 0;
 	int isize = 4;
@@ -760,16 +759,15 @@ do_alignment(unsigned long addr, unsigne
 
 	instrptr = instruction_pointer(regs);
 
-	fs = get_fs();
-	set_fs(KERNEL_DS);
 	if (thumb_mode(regs)) {
-		fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
+		u16 *ptr = (u16 *)(instrptr & ~1);
+		fault = probe_kernel_address(ptr, tinstr);
 		if (!fault) {
 			if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
 			    IS_T32(tinstr)) {
 				/* Thumb-2 32-bit */
 				u16 tinst2 = 0;
-				fault = __get_user(tinst2, (u16 *)(instrptr+2));
+				fault = probe_kernel_address(ptr + 1, tinst2);
 				instr = (tinstr << 16) | tinst2;
 				thumb2_32b = 1;
 			} else {
@@ -778,8 +776,7 @@ do_alignment(unsigned long addr, unsigne
 			}
 		}
 	} else
-		fault = __get_user(instr, (u32 *)instrptr);
-	set_fs(fs);
+		fault = probe_kernel_address(instrptr, instr);
 
 	if (fault) {
 		type = TYPE_FAULT;
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/cache-feroceon-l2.c linux-libre-3.8.13-gnu1/arch/arm/mm/cache-feroceon-l2.c
--- linux-libre-3.8-gnu1/arch/arm/mm/cache-feroceon-l2.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/cache-feroceon-l2.c	2013-05-11 16:57:46.000000000 -0400
@@ -343,6 +343,7 @@ void __init feroceon_l2_init(int __l2_wt
 	outer_cache.inv_range = feroceon_l2_inv_range;
 	outer_cache.clean_range = feroceon_l2_clean_range;
 	outer_cache.flush_range = feroceon_l2_flush_range;
+	outer_cache.inv_all = l2_inv_all;
 
 	enable_l2();
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/context.c linux-libre-3.8.13-gnu1/arch/arm/mm/context.c
--- linux-libre-3.8-gnu1/arch/arm/mm/context.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/context.c	2013-05-11 16:57:46.000000000 -0400
@@ -149,9 +149,9 @@ static int is_reserved_asid(u64 asid)
 	return 0;
 }
 
-static void new_context(struct mm_struct *mm, unsigned int cpu)
+static u64 new_context(struct mm_struct *mm, unsigned int cpu)
 {
-	u64 asid = mm->context.id;
+	u64 asid = atomic64_read(&mm->context.id);
 	u64 generation = atomic64_read(&asid_generation);
 
 	if (asid != 0 && is_reserved_asid(asid)) {
@@ -178,13 +178,14 @@ static void new_context(struct mm_struct
 		cpumask_clear(mm_cpumask(mm));
 	}
 
-	mm->context.id = asid;
+	return asid;
 }
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
 {
 	unsigned long flags;
 	unsigned int cpu = smp_processor_id();
+	u64 asid;
 
 	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
 		__check_vmalloc_seq(mm);
@@ -195,20 +196,24 @@ void check_and_switch_context(struct mm_
 	 */
 	cpu_set_reserved_ttbr0();
 
-	if (!((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
-	    && atomic64_xchg(&per_cpu(active_asids, cpu), mm->context.id))
+	asid = atomic64_read(&mm->context.id);
+	if (!((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS)
+	    && atomic64_xchg(&per_cpu(active_asids, cpu), asid))
 		goto switch_mm_fastpath;
 
 	raw_spin_lock_irqsave(&cpu_asid_lock, flags);
 	/* Check that our ASID belongs to the current generation. */
-	if ((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
-		new_context(mm, cpu);
-
-	atomic64_set(&per_cpu(active_asids, cpu), mm->context.id);
-	cpumask_set_cpu(cpu, mm_cpumask(mm));
+	asid = atomic64_read(&mm->context.id);
+	if ((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) {
+		asid = new_context(mm, cpu);
+		atomic64_set(&mm->context.id, asid);
+	}
 
 	if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
 		local_flush_tlb_all();
+
+	atomic64_set(&per_cpu(active_asids, cpu), asid);
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
 	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
 switch_mm_fastpath:
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/dma-mapping.c linux-libre-3.8.13-gnu1/arch/arm/mm/dma-mapping.c
--- linux-libre-3.8-gnu1/arch/arm/mm/dma-mapping.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/dma-mapping.c	2013-05-11 16:57:46.000000000 -0400
@@ -330,6 +330,7 @@ static int __init atomic_pool_init(void)
 {
 	struct dma_pool *pool = &atomic_pool;
 	pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
+	gfp_t gfp = GFP_KERNEL | GFP_DMA;
 	unsigned long nr_pages = pool->size >> PAGE_SHIFT;
 	unsigned long *bitmap;
 	struct page *page;
@@ -348,8 +349,8 @@ static int __init atomic_pool_init(void)
 	if (IS_ENABLED(CONFIG_CMA))
 		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
 	else
-		ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
-					   &page, NULL);
+		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
+					   NULL);
 	if (ptr) {
 		int i;
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-arm920.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-arm920.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-arm920.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-arm920.S	2013-05-11 16:57:46.000000000 -0400
@@ -387,7 +387,7 @@ ENTRY(cpu_arm920_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm920_suspend_size
 .equ	cpu_arm920_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_arm920_do_suspend)
 	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ PID
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-arm926.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-arm926.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-arm926.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-arm926.S	2013-05-11 16:57:46.000000000 -0400
@@ -402,7 +402,7 @@ ENTRY(cpu_arm926_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm926_suspend_size
 .equ	cpu_arm926_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_arm926_do_suspend)
 	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ PID
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-mohawk.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-mohawk.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-mohawk.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-mohawk.S	2013-05-11 16:57:46.000000000 -0400
@@ -350,7 +350,7 @@ ENTRY(cpu_mohawk_set_pte_ext)
 
 .globl	cpu_mohawk_suspend_size
 .equ	cpu_mohawk_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_mohawk_do_suspend)
 	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-sa1100.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-sa1100.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-sa1100.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-sa1100.S	2013-05-11 16:57:46.000000000 -0400
@@ -172,7 +172,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
 
 .globl	cpu_sa1100_suspend_size
 .equ	cpu_sa1100_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_sa1100_do_suspend)
 	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-v6.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-v6.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-v6.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-v6.S	2013-05-11 16:57:46.000000000 -0400
@@ -138,7 +138,7 @@ ENTRY(cpu_v6_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl	cpu_v6_suspend_size
 .equ	cpu_v6_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v6_do_suspend)
 	stmfd	sp!, {r4 - r9, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-xsc3.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-xsc3.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-xsc3.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-xsc3.S	2013-05-11 16:57:46.000000000 -0400
@@ -413,7 +413,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
 
 .globl	cpu_xsc3_suspend_size
 .equ	cpu_xsc3_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_xsc3_do_suspend)
 	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
diff -druNp linux-libre-3.8-gnu1/arch/arm/mm/proc-xscale.S linux-libre-3.8.13-gnu1/arch/arm/mm/proc-xscale.S
--- linux-libre-3.8-gnu1/arch/arm/mm/proc-xscale.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/mm/proc-xscale.S	2013-05-11 16:57:46.000000000 -0400
@@ -528,7 +528,7 @@ ENTRY(cpu_xscale_set_pte_ext)
 
 .globl	cpu_xscale_suspend_size
 .equ	cpu_xscale_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_xscale_do_suspend)
 	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
diff -druNp linux-libre-3.8-gnu1/arch/arm/plat-samsung/include/plat/debug-macro.S linux-libre-3.8.13-gnu1/arch/arm/plat-samsung/include/plat/debug-macro.S
--- linux-libre-3.8-gnu1/arch/arm/plat-samsung/include/plat/debug-macro.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/plat-samsung/include/plat/debug-macro.S	2013-05-11 16:57:46.000000000 -0400
@@ -14,12 +14,12 @@
 /* The S5PV210/S5PC110 implementations are as belows. */
 
 	.macro fifo_level_s5pv210 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		and	\rd, \rd, #S5PV210_UFSTAT_TXMASK
 	.endm
 
 	.macro  fifo_full_s5pv210 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		tst	\rd, #S5PV210_UFSTAT_TXFULL
 	.endm
 
@@ -27,7 +27,7 @@
  * most widely re-used */
 
 	.macro fifo_level_s3c2440 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		and	\rd, \rd, #S3C2440_UFSTAT_TXMASK
 	.endm
 
@@ -36,7 +36,7 @@
 #endif
 
 	.macro  fifo_full_s3c2440 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UFSTAT]
 		tst	\rd, #S3C2440_UFSTAT_TXFULL
 	.endm
 
@@ -45,11 +45,11 @@
 #endif
 
 	.macro	senduart,rd,rx
-		strb 	\rd, [\rx, # S3C2410_UTXH ]
+		strb 	\rd, [\rx, # S3C2410_UTXH]
 	.endm
 
 	.macro	busyuart, rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFCON ]
+		ldr	\rd, [\rx, # S3C2410_UFCON]
 		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
 		beq	1001f				@
 		@ FIFO enabled...
@@ -60,7 +60,7 @@
 
 1001:
 		@ busy waiting for non fifo
-		ldr	\rd, [ \rx, # S3C2410_UTRSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UTRSTAT]
 		tst	\rd, #S3C2410_UTRSTAT_TXFE
 		beq	1001b
 
@@ -68,7 +68,7 @@
 	.endm
 
 	.macro	waituart,rd,rx
-		ldr	\rd, [ \rx, # S3C2410_UFCON ]
+		ldr	\rd, [\rx, # S3C2410_UFCON]
 		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
 		beq	1001f				@
 		@ FIFO enabled...
@@ -79,7 +79,7 @@
 		b	1002f
 1001:
 		@ idle waiting for non fifo
-		ldr	\rd, [ \rx, # S3C2410_UTRSTAT ]
+		ldr	\rd, [\rx, # S3C2410_UTRSTAT]
 		tst	\rd, #S3C2410_UTRSTAT_TXFE
 		beq	1001b
 
diff -druNp linux-libre-3.8-gnu1/arch/arm/vfp/vfpmodule.c linux-libre-3.8.13-gnu1/arch/arm/vfp/vfpmodule.c
--- linux-libre-3.8-gnu1/arch/arm/vfp/vfpmodule.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/vfp/vfpmodule.c	2013-05-11 16:57:46.000000000 -0400
@@ -413,7 +413,7 @@ void VFP_bounce(u32 trigger, u32 fpexc,
 	 * If there isn't a second FP instruction, exit now. Note that
 	 * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
 	 */
-	if (fpexc ^ (FPEXC_EX | FPEXC_FP2V))
+	if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
 		goto exit;
 
 	/*
diff -druNp linux-libre-3.8-gnu1/arch/arm/xen/enlighten.c linux-libre-3.8.13-gnu1/arch/arm/xen/enlighten.c
--- linux-libre-3.8-gnu1/arch/arm/xen/enlighten.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm/xen/enlighten.c	2013-05-11 16:57:46.000000000 -0400
@@ -237,7 +237,7 @@ static int __init xen_init_events(void)
 	xen_init_IRQ();
 
 	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
-			"events", xen_vcpu)) {
+			"events", &xen_vcpu)) {
 		pr_err("Error requesting IRQ %d\n", xen_events_irq);
 		return -EINVAL;
 	}
diff -druNp linux-libre-3.8-gnu1/arch/arm64/kernel/signal32.c linux-libre-3.8.13-gnu1/arch/arm64/kernel/signal32.c
--- linux-libre-3.8-gnu1/arch/arm64/kernel/signal32.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm64/kernel/signal32.c	2013-05-11 16:57:46.000000000 -0400
@@ -76,7 +76,7 @@ struct compat_sigcontext {
 
 struct compat_ucontext {
 	compat_ulong_t			uc_flags;
-	struct compat_ucontext		*uc_link;
+	compat_uptr_t			uc_link;
 	compat_stack_t			uc_stack;
 	struct compat_sigcontext	uc_mcontext;
 	compat_sigset_t			uc_sigmask;
@@ -703,7 +703,7 @@ int compat_setup_rt_frame(int usig, stru
 	err |= copy_siginfo_to_user32(&frame->info, info);
 
 	__put_user_error(0, &frame->sig.uc.uc_flags, err);
-	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
+	__put_user_error(0, &frame->sig.uc.uc_link, err);
 
 	memset(&stack, 0, sizeof(stack));
 	stack.ss_sp = (compat_uptr_t)current->sas_ss_sp;
diff -druNp linux-libre-3.8-gnu1/arch/arm64/mm/fault.c linux-libre-3.8.13-gnu1/arch/arm64/mm/fault.c
--- linux-libre-3.8-gnu1/arch/arm64/mm/fault.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/arm64/mm/fault.c	2013-05-11 16:57:46.000000000 -0400
@@ -148,6 +148,7 @@ void do_bad_area(unsigned long addr, uns
 #define VM_FAULT_BADACCESS	0x020000
 
 #define ESR_WRITE		(1 << 6)
+#define ESR_CM			(1 << 8)
 #define ESR_LNX_EXEC		(1 << 24)
 
 /*
@@ -206,7 +207,7 @@ static int __kprobes do_page_fault(unsig
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	int fault, sig, code;
-	int write = esr & ESR_WRITE;
+	bool write = (esr & ESR_WRITE) && !(esr & ESR_CM);
 	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
 		(write ? FAULT_FLAG_WRITE : 0);
 
diff -druNp linux-libre-3.8-gnu1/arch/avr32/configs/favr-32_defconfig linux-libre-3.8.13-gnu1/arch/avr32/configs/favr-32_defconfig
--- linux-libre-3.8-gnu1/arch/avr32/configs/favr-32_defconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/avr32/configs/favr-32_defconfig	2013-05-11 16:57:46.000000000 -0400
@@ -122,7 +122,6 @@ CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_ATMELMCI_DMA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=m
diff -druNp linux-libre-3.8-gnu1/arch/avr32/configs/merisc_defconfig linux-libre-3.8.13-gnu1/arch/avr32/configs/merisc_defconfig
--- linux-libre-3.8-gnu1/arch/avr32/configs/merisc_defconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/avr32/configs/merisc_defconfig	2013-05-11 16:57:46.000000000 -0400
@@ -102,7 +102,6 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_ATMELMCI_DMA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=y
diff -druNp linux-libre-3.8-gnu1/arch/avr32/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/avr32/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/avr32/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/avr32/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -29,6 +29,7 @@ struct sigaction {
 	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/cris/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/cris/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/cris/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/cris/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -29,6 +29,7 @@ struct sigaction {
 	void (*sa_restorer)(void);
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/h8300/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/h8300/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/h8300/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/h8300/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -29,6 +29,7 @@ struct sigaction {
 	void (*sa_restorer)(void);
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/ia64/include/asm/futex.h linux-libre-3.8.13-gnu1/arch/ia64/include/asm/futex.h
--- linux-libre-3.8-gnu1/arch/ia64/include/asm/futex.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/ia64/include/asm/futex.h	2013-05-11 16:57:46.000000000 -0400
@@ -106,16 +106,15 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
 		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
-			"	mov %0=r0				\n"
 			"	mov ar.ccv=%4;;				\n"
 			"[1:]	cmpxchg4.acq %1=[%2],%3,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8), "=r" (prev)
+			: "+r" (r8), "=&r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
diff -druNp linux-libre-3.8-gnu1/arch/ia64/include/asm/mca.h linux-libre-3.8.13-gnu1/arch/ia64/include/asm/mca.h
--- linux-libre-3.8-gnu1/arch/ia64/include/asm/mca.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/ia64/include/asm/mca.h	2013-05-11 16:57:46.000000000 -0400
@@ -143,6 +143,7 @@ extern unsigned long __per_cpu_mca[NR_CP
 extern int cpe_vector;
 extern int ia64_cpe_irq;
 extern void ia64_mca_init(void);
+extern void ia64_mca_irq_init(void);
 extern void ia64_mca_cpu_init(void *);
 extern void ia64_os_mca_dispatch(void);
 extern void ia64_os_mca_dispatch_end(void);
diff -druNp linux-libre-3.8-gnu1/arch/ia64/kernel/irq.c linux-libre-3.8.13-gnu1/arch/ia64/kernel/irq.c
--- linux-libre-3.8-gnu1/arch/ia64/kernel/irq.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/ia64/kernel/irq.c	2013-05-11 16:57:46.000000000 -0400
@@ -23,6 +23,8 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/mca.h>
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -83,6 +85,12 @@ bool is_affinity_mask_valid(const struct
 
 #endif /* CONFIG_SMP */
 
+int __init arch_early_irq_init(void)
+{
+	ia64_mca_irq_init();
+	return 0;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 unsigned int vectors_in_migration[NR_IRQS];
 
diff -druNp linux-libre-3.8-gnu1/arch/ia64/kernel/mca.c linux-libre-3.8.13-gnu1/arch/ia64/kernel/mca.c
--- linux-libre-3.8-gnu1/arch/ia64/kernel/mca.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/ia64/kernel/mca.c	2013-05-11 16:57:46.000000000 -0400
@@ -2074,22 +2074,16 @@ ia64_mca_init(void)
 	printk(KERN_INFO "MCA related initialization done\n");
 }
 
+
 /*
- * ia64_mca_late_init
- *
- *	Opportunity to setup things that require initialization later
- *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
- *	platform doesn't support an interrupt driven mechanism.
- *
- *  Inputs  :   None
- *  Outputs :   Status
+ * These pieces cannot be done in ia64_mca_init() because it is called before
+ * early_irq_init() which would wipe out our percpu irq registrations. But we
+ * cannot leave them until ia64_mca_late_init() because by then all the other
+ * processors have been brought online and have set their own CMC vectors to
+ * point at a non-existant action. Called from arch_early_irq_init().
  */
-static int __init
-ia64_mca_late_init(void)
+void __init ia64_mca_irq_init(void)
 {
-	if (!mca_init)
-		return 0;
-
 	/*
 	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
 	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
@@ -2108,6 +2102,23 @@ ia64_mca_late_init(void)
 	/* Setup the CPEI/P handler */
 	register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
 #endif
+}
+
+/*
+ * ia64_mca_late_init
+ *
+ *	Opportunity to setup things that require initialization later
+ *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
+ *	platform doesn't support an interrupt driven mechanism.
+ *
+ *  Inputs  :   None
+ *  Outputs :   Status
+ */
+static int __init
+ia64_mca_late_init(void)
+{
+	if (!mca_init)
+		return 0;
 
 	register_hotcpu_notifier(&mca_cpu_notifier);
 
diff -druNp linux-libre-3.8-gnu1/arch/ia64/kvm/vtlb.c linux-libre-3.8.13-gnu1/arch/ia64/kvm/vtlb.c
--- linux-libre-3.8-gnu1/arch/ia64/kvm/vtlb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/ia64/kvm/vtlb.c	2013-05-11 16:57:46.000000000 -0400
@@ -256,7 +256,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
 			"srlz.d;;"
 			"ssm psr.i;;"
 			"srlz.d;;"
-			: "=r"(ret) : "r"(iha), "r"(pte):"memory");
+			: "=&r"(ret) : "r"(iha), "r"(pte) : "memory");
 
 	return ret;
 }
diff -druNp linux-libre-3.8-gnu1/arch/m32r/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/m32r/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/m32r/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/m32r/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -22,6 +22,7 @@ struct sigaction {
 	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/m68k/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/m68k/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/m68k/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/m68k/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -29,6 +29,7 @@ struct sigaction {
 	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/mips/include/asm/page.h linux-libre-3.8.13-gnu1/arch/mips/include/asm/page.h
--- linux-libre-3.8-gnu1/arch/mips/include/asm/page.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/mips/include/asm/page.h	2013-05-11 16:57:46.000000000 -0400
@@ -31,7 +31,7 @@
 #define PAGE_SHIFT	16
 #endif
 #define PAGE_SIZE	(_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK       (~(PAGE_SIZE - 1))
+#define PAGE_MASK	(~((1 << PAGE_SHIFT) - 1))
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 #define HPAGE_SHIFT	(PAGE_SHIFT + PAGE_SHIFT - 3)
diff -druNp linux-libre-3.8-gnu1/arch/mips/kernel/mcount.S linux-libre-3.8.13-gnu1/arch/mips/kernel/mcount.S
--- linux-libre-3.8-gnu1/arch/mips/kernel/mcount.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/mips/kernel/mcount.S	2013-05-11 16:57:46.000000000 -0400
@@ -46,10 +46,9 @@
 	PTR_L	a5, PT_R9(sp)
 	PTR_L	a6, PT_R10(sp)
 	PTR_L	a7, PT_R11(sp)
-#else
-	PTR_ADDIU	sp, PT_SIZE
 #endif
-.endm
+	PTR_ADDIU	sp, PT_SIZE
+	.endm
 
 	.macro RETURN_BACK
 	jr ra
@@ -68,7 +67,11 @@ NESTED(ftrace_caller, PT_SIZE, ra)
 	.globl _mcount
 _mcount:
 	b	ftrace_stub
-	addiu sp,sp,8
+#ifdef CONFIG_32BIT
+	 addiu sp,sp,8
+#else
+	 nop
+#endif
 
 	/* When tracing is activated, it calls ftrace_caller+8 (aka here) */
 	lw	t1, function_trace_stop
diff -druNp linux-libre-3.8-gnu1/arch/mips/lib/bitops.c linux-libre-3.8.13-gnu1/arch/mips/lib/bitops.c
--- linux-libre-3.8-gnu1/arch/mips/lib/bitops.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/mips/lib/bitops.c	2013-05-11 16:57:46.000000000 -0400
@@ -90,12 +90,12 @@ int __mips_test_and_set_bit(unsigned lon
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a |= mask;
 	raw_local_irq_restore(flags);
 	return res;
@@ -116,12 +116,12 @@ int __mips_test_and_set_bit_lock(unsigne
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a |= mask;
 	raw_local_irq_restore(flags);
 	return res;
@@ -141,12 +141,12 @@ int __mips_test_and_clear_bit(unsigned l
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a &= ~mask;
 	raw_local_irq_restore(flags);
 	return res;
@@ -166,12 +166,12 @@ int __mips_test_and_change_bit(unsigned
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a ^= mask;
 	raw_local_irq_restore(flags);
 	return res;
diff -druNp linux-libre-3.8-gnu1/arch/mn10300/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/mn10300/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/mn10300/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/mn10300/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -39,6 +39,7 @@ struct sigaction {
 	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/parisc/include/asm/pgtable.h linux-libre-3.8.13-gnu1/arch/parisc/include/asm/pgtable.h
--- linux-libre-3.8-gnu1/arch/parisc/include/asm/pgtable.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/parisc/include/asm/pgtable.h	2013-05-11 16:57:46.000000000 -0400
@@ -12,11 +12,10 @@
 
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
+#include <linux/mm_types.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 
-struct vm_area_struct;
-
 /*
  * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
  * memory.  For the return value to be meaningful, ADDR must be >=
@@ -40,7 +39,14 @@ struct vm_area_struct;
         do{                                                     \
                 *(pteptr) = (pteval);                           \
         } while(0)
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+extern void purge_tlb_entries(struct mm_struct *, unsigned long);
+
+#define set_pte_at(mm, addr, ptep, pteval)                      \
+	do {                                                    \
+		set_pte(ptep, pteval);                          \
+		purge_tlb_entries(mm, addr);                    \
+	} while (0)
 
 #endif /* !__ASSEMBLY__ */
 
@@ -466,6 +472,7 @@ static inline void ptep_set_wrprotect(st
 		old = pte_val(*ptep);
 		new = pte_val(pte_wrprotect(__pte (old)));
 	} while (cmpxchg((unsigned long *) ptep, old, new) != old);
+	purge_tlb_entries(mm, addr);
 #else
 	pte_t old_pte = *ptep;
 	set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
diff -druNp linux-libre-3.8-gnu1/arch/parisc/kernel/cache.c linux-libre-3.8.13-gnu1/arch/parisc/kernel/cache.c
--- linux-libre-3.8-gnu1/arch/parisc/kernel/cache.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/parisc/kernel/cache.c	2013-05-11 16:57:46.000000000 -0400
@@ -419,6 +419,24 @@ void kunmap_parisc(void *addr)
 EXPORT_SYMBOL(kunmap_parisc);
 #endif
 
+void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
+{
+	unsigned long flags;
+
+	/* Note: purge_tlb_entries can be called at startup with
+	   no context.  */
+
+	/* Disable preemption while we play with %sr1.  */
+	preempt_disable();
+	mtsp(mm->context, 1);
+	purge_tlb_start(flags);
+	pdtlb(addr);
+	pitlb(addr);
+	purge_tlb_end(flags);
+	preempt_enable();
+}
+EXPORT_SYMBOL(purge_tlb_entries);
+
 void __flush_tlb_range(unsigned long sid, unsigned long start,
 		       unsigned long end)
 {
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/include/asm/eeh.h linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/eeh.h
--- linux-libre-3.8-gnu1/arch/powerpc/include/asm/eeh.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/eeh.h	2013-05-11 16:57:46.000000000 -0400
@@ -201,6 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev
 void __init eeh_addr_cache_build(void);
 void eeh_add_device_tree_early(struct device_node *);
 void eeh_add_device_tree_late(struct pci_bus *);
+void eeh_add_sysfs_files(struct pci_bus *);
 void eeh_remove_bus_device(struct pci_dev *, int);
 
 /**
@@ -240,6 +241,8 @@ static inline void eeh_add_device_tree_e
 
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
 
+static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
+
 static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
 
 static inline void eeh_lock(void) { }
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/include/asm/mmu-hash64.h linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/mmu-hash64.h
--- linux-libre-3.8-gnu1/arch/powerpc/include/asm/mmu-hash64.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/mmu-hash64.h	2013-05-11 16:57:46.000000000 -0400
@@ -343,17 +343,16 @@ extern void slb_set_size(u16 size);
 /*
  * VSID allocation (256MB segment)
  *
- * We first generate a 38-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID | 1 << 37, for user addresses it is:
- *	(context << USER_ESID_BITS) | (esid & ((1U << USER_ESID_BITS) - 1)
- *
- * This splits the proto-VSID into the below range
- *  0 - (2^(CONTEXT_BITS + USER_ESID_BITS) - 1) : User proto-VSID range
- *  2^(CONTEXT_BITS + USER_ESID_BITS) - 2^(VSID_BITS) : Kernel proto-VSID range
+ * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated
+ * from mmu context id and effective segment id of the address.
  *
- * We also have CONTEXT_BITS + USER_ESID_BITS = VSID_BITS - 1
- * That is, we assign half of the space to user processes and half
- * to the kernel.
+ * For user processes max context id is limited to ((1ul << 19) - 5)
+ * for kernel space, we use the top 4 context ids to map address as below
+ * NOTE: each context only support 64TB now.
+ * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
+ * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
+ * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
+ * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
  *
  * The proto-VSIDs are then scrambled into real VSIDs with the
  * multiplicative hash:
@@ -363,41 +362,49 @@ extern void slb_set_size(u16 size);
  * VSID_MULTIPLIER is prime, so in particular it is
  * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
  * Because the modulus is 2^n-1 we can compute it efficiently without
- * a divide or extra multiply (see below).
- *
- * This scheme has several advantages over older methods:
- *
- *	- We have VSIDs allocated for every kernel address
- * (i.e. everything above 0xC000000000000000), except the very top
- * segment, which simplifies several things.
+ * a divide or extra multiply (see below). The scramble function gives
+ * robust scattering in the hash table (at least based on some initial
+ * results).
  *
- *	- We allow for USER_ESID_BITS significant bits of ESID and
- * CONTEXT_BITS  bits of context for user addresses.
- *  i.e. 64T (46 bits) of address space for up to half a million contexts.
+ * We also consider VSID 0 special. We use VSID 0 for slb entries mapping
+ * bad address. This enables us to consolidate bad address handling in
+ * hash_page.
  *
- *	- The scramble function gives robust scattering in the hash
- * table (at least based on some initial results).  The previous
- * method was more susceptible to pathological cases giving excessive
- * hash collisions.
+ * We also need to avoid the last segment of the last context, because that
+ * would give a protovsid of 0x1fffffffff. That will result in a VSID 0
+ * because of the modulo operation in vsid scramble. But the vmemmap
+ * (which is what uses region 0xf) will never be close to 64TB in size
+ * (it's 56 bytes per page of system memory).
+ */
+
+#define CONTEXT_BITS		19
+#define ESID_BITS		18
+#define ESID_BITS_1T		6
+
+/*
+ * 256MB segment
+ * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments
+ * available for user + kernel mapping. The top 4 contexts are used for
+ * kernel mapping. Each segment contains 2^28 bytes. Each
+ * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
+ * (19 == 37 + 28 - 46).
  */
+#define MAX_USER_CONTEXT	((ASM_CONST(1) << CONTEXT_BITS) - 5)
 
 /*
  * This should be computed such that protovosid * vsid_mulitplier
  * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
  */
 #define VSID_MULTIPLIER_256M	ASM_CONST(12538073)	/* 24-bit prime */
-#define VSID_BITS_256M		38
+#define VSID_BITS_256M		(CONTEXT_BITS + ESID_BITS)
 #define VSID_MODULUS_256M	((1UL<<VSID_BITS_256M)-1)
 
 #define VSID_MULTIPLIER_1T	ASM_CONST(12538073)	/* 24-bit prime */
-#define VSID_BITS_1T		26
+#define VSID_BITS_1T		(CONTEXT_BITS + ESID_BITS_1T)
 #define VSID_MODULUS_1T		((1UL<<VSID_BITS_1T)-1)
 
-#define CONTEXT_BITS		19
-#define USER_ESID_BITS		18
-#define USER_ESID_BITS_1T	6
 
-#define USER_VSID_RANGE	(1UL << (USER_ESID_BITS + SID_SHIFT))
+#define USER_VSID_RANGE	(1UL << (ESID_BITS + SID_SHIFT))
 
 /*
  * This macro generates asm code to compute the VSID scramble
@@ -421,7 +428,8 @@ extern void slb_set_size(u16 size);
 	srdi	rx,rt,VSID_BITS_##size;					\
 	clrldi	rt,rt,(64-VSID_BITS_##size);				\
 	add	rt,rt,rx;		/* add high and low bits */	\
-	/* Now, r3 == VSID (mod 2^36-1), and lies between 0 and		\
+	/* NOTE: explanation based on VSID_BITS_##size = 36		\
+	 * Now, r3 == VSID (mod 2^36-1), and lies between 0 and		\
 	 * 2^36-1+2^28-1.  That in particular means that if r3 >=	\
 	 * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has	\
 	 * the bit clear, r3 already has the answer we want, if it	\
@@ -513,34 +521,6 @@ typedef struct {
 	})
 #endif /* 1 */
 
-/*
- * This is only valid for addresses >= PAGE_OFFSET
- * The proto-VSID space is divided into two class
- * User:   0 to 2^(CONTEXT_BITS + USER_ESID_BITS) -1
- * kernel: 2^(CONTEXT_BITS + USER_ESID_BITS) to 2^(VSID_BITS) - 1
- *
- * With KERNEL_START at 0xc000000000000000, the proto vsid for
- * the kernel ends up with 0xc00000000 (36 bits). With 64TB
- * support we need to have kernel proto-VSID in the
- * [2^37 to 2^38 - 1] range due to the increased USER_ESID_BITS.
- */
-static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
-{
-	unsigned long proto_vsid;
-	/*
-	 * We need to make sure proto_vsid for the kernel is
-	 * >= 2^(CONTEXT_BITS + USER_ESID_BITS[_1T])
-	 */
-	if (ssize == MMU_SEGSIZE_256M) {
-		proto_vsid = ea >> SID_SHIFT;
-		proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS));
-		return vsid_scramble(proto_vsid, 256M);
-	}
-	proto_vsid = ea >> SID_SHIFT_1T;
-	proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS_1T));
-	return vsid_scramble(proto_vsid, 1T);
-}
-
 /* Returns the segment size indicator for a user address */
 static inline int user_segment_size(unsigned long addr)
 {
@@ -550,17 +530,41 @@ static inline int user_segment_size(unsi
 	return MMU_SEGSIZE_256M;
 }
 
-/* This is only valid for user addresses (which are below 2^44) */
 static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
 				     int ssize)
 {
+	/*
+	 * Bad address. We return VSID 0 for that
+	 */
+	if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
+		return 0;
+
 	if (ssize == MMU_SEGSIZE_256M)
-		return vsid_scramble((context << USER_ESID_BITS)
+		return vsid_scramble((context << ESID_BITS)
 				     | (ea >> SID_SHIFT), 256M);
-	return vsid_scramble((context << USER_ESID_BITS_1T)
+	return vsid_scramble((context << ESID_BITS_1T)
 			     | (ea >> SID_SHIFT_1T), 1T);
 }
 
+/*
+ * This is only valid for addresses >= PAGE_OFFSET
+ *
+ * For kernel space, we use the top 4 context ids to map address as below
+ * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
+ * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
+ * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
+ * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
+ */
+static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
+{
+	unsigned long context;
+
+	/*
+	 * kernel take the top 4 context from the available range
+	 */
+	context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1;
+	return get_vsid(context, ea, ssize);
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_MMU_HASH64_H_ */
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/include/asm/ppc-opcode.h linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-3.8-gnu1/arch/powerpc/include/asm/ppc-opcode.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/ppc-opcode.h	2013-05-11 16:57:46.000000000 -0400
@@ -112,6 +112,10 @@
 #define PPC_INST_MFSPR_DSCR_MASK	0xfc1fffff
 #define PPC_INST_MTSPR_DSCR		0x7c1103a6
 #define PPC_INST_MTSPR_DSCR_MASK	0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_USER	0x7c0302a6
+#define PPC_INST_MFSPR_DSCR_USER_MASK	0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_USER	0x7c0303a6
+#define PPC_INST_MTSPR_DSCR_USER_MASK	0xfc1fffff
 #define PPC_INST_SLBFEE			0x7c0007a7
 
 #define PPC_INST_STRING			0x7c00042a
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/powerpc/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -1,6 +1,7 @@
 #ifndef _ASM_POWERPC_SIGNAL_H
 #define _ASM_POWERPC_SIGNAL_H
 
+#define __ARCH_HAS_SA_RESTORER
 #include <uapi/asm/signal.h>
 
 #endif /* _ASM_POWERPC_SIGNAL_H */
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/Kconfig linux-libre-3.8.13-gnu1/arch/powerpc/Kconfig
--- linux-libre-3.8-gnu1/arch/powerpc/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -275,6 +275,10 @@ config PPC_ADV_DEBUG_DAC_RANGE
 	depends on PPC_ADV_DEBUG_REGS && 44x
 	default y
 
+config PPC_EMULATE_SSTEP
+	bool
+	default y if KPROBES || UPROBES || XMON || HAVE_HW_BREAKPOINT
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/cpu_setup_power.S linux-libre-3.8.13-gnu1/arch/powerpc/kernel/cpu_setup_power.S
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/cpu_setup_power.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/cpu_setup_power.S	2013-05-11 16:57:46.000000000 -0400
@@ -64,6 +64,7 @@ _GLOBAL(__restore_cpu_power8)
 	mflr	r11
 	mfmsr	r3
 	rldicl.	r0,r3,4,63
+	mtlr	r11
 	beqlr
 	li	r0,0
 	mtspr	SPRN_LPID,r0
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/cputable.c linux-libre-3.8.13-gnu1/arch/powerpc/kernel/cputable.c
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/cputable.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/cputable.c	2013-05-11 16:57:46.000000000 -0400
@@ -275,7 +275,7 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_features		= CPU_FTRS_PPC970,
 		.cpu_user_features	= COMMON_USER_POWER4 |
 			PPC_FEATURE_HAS_ALTIVEC_COMP,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
+		.mmu_features		= MMU_FTRS_PPC970,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/entry_64.S linux-libre-3.8.13-gnu1/arch/powerpc/kernel/entry_64.S
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/entry_64.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/entry_64.S	2013-05-11 16:57:46.000000000 -0400
@@ -634,7 +634,7 @@ resume_kernel:
 	/* Clear _TIF_EMULATE_STACK_STORE flag */
 	lis	r11,_TIF_EMULATE_STACK_STORE@h
 	addi	r5,r9,TI_FLAGS
-	ldarx	r4,0,r5
+0:	ldarx	r4,0,r5
 	andc	r4,r4,r11
 	stdcx.	r4,0,r5
 	bne-	0b
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/exceptions-64s.S linux-libre-3.8.13-gnu1/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/exceptions-64s.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/exceptions-64s.S	2013-05-11 16:57:46.000000000 -0400
@@ -740,7 +740,7 @@ hardware_interrupt_relon_hv:
 		_MASKABLE_RELON_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV, SOFTEN_TEST_HV)
 	FTR_SECTION_ELSE
 		_MASKABLE_RELON_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD, SOFTEN_TEST_PR)
-	ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_206)
+	ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
 	STD_RELON_EXCEPTION_PSERIES(0x4600, 0x600, alignment)
 	STD_RELON_EXCEPTION_PSERIES(0x4700, 0x700, program_check)
 	STD_RELON_EXCEPTION_PSERIES(0x4800, 0x800, fp_unavailable)
@@ -1268,20 +1268,36 @@ do_ste_alloc:
 _GLOBAL(do_stab_bolted)
 	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
 	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
+	mfspr	r11,SPRN_DAR			/* ea */
+
+	/*
+	 * check for bad kernel/user address
+	 * (ea & ~REGION_MASK) >= PGTABLE_RANGE
+	 */
+	rldicr. r9,r11,4,(63 - 46 - 4)
+	li	r9,0	/* VSID = 0 for bad address */
+	bne-	0f
+
+	/*
+	 * Calculate VSID:
+	 * This is the kernel vsid, we take the top for context from
+	 * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
+	 * Here we know that (ea >> 60) == 0xc
+	 */
+	lis	r9,(MAX_USER_CONTEXT + 1)@ha
+	addi	r9,r9,(MAX_USER_CONTEXT + 1)@l
 
+	srdi	r10,r11,SID_SHIFT
+	rldimi  r10,r9,ESID_BITS,0 /* proto vsid */
+	ASM_VSID_SCRAMBLE(r10, r9, 256M)
+	rldic	r9,r10,12,16	/* r9 = vsid << 12 */
+
+0:
 	/* Hash to the primary group */
 	ld	r10,PACASTABVIRT(r13)
-	mfspr	r11,SPRN_DAR
-	srdi	r11,r11,28
+	srdi	r11,r11,SID_SHIFT
 	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
 
-	/* Calculate VSID */
-	/* This is a kernel address, so protovsid = ESID | 1 << 37 */
-	li	r9,0x1
-	rldimi  r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0
-	ASM_VSID_SCRAMBLE(r11, r9, 256M)
-	rldic	r9,r11,12,16	/* r9 = vsid << 12 */
-
 	/* Search the primary group for a free entry */
 1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
 	andi.	r11,r11,0x80
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/head_64.S linux-libre-3.8.13-gnu1/arch/powerpc/kernel/head_64.S
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/head_64.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/head_64.S	2013-05-11 16:57:46.000000000 -0400
@@ -490,6 +490,7 @@ _GLOBAL(copy_and_flush)
 	sync
 	addi	r5,r5,8
 	addi	r6,r6,8
+	isync
 	blr
 
 .align 8
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/machine_kexec_64.c linux-libre-3.8.13-gnu1/arch/powerpc/kernel/machine_kexec_64.c
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/machine_kexec_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/machine_kexec_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -162,6 +162,8 @@ static int kexec_all_irq_disabled = 0;
 static void kexec_smp_down(void *arg)
 {
 	local_irq_disable();
+	hard_irq_disable();
+
 	mb(); /* make sure our irqs are disabled before we say they are */
 	get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
 	while(kexec_all_irq_disabled == 0)
@@ -244,6 +246,8 @@ static void kexec_prepare_cpus(void)
 	wake_offline_cpus();
 	smp_call_function(kexec_smp_down, NULL, /* wait */0);
 	local_irq_disable();
+	hard_irq_disable();
+
 	mb(); /* make sure IRQs are disabled before we say they are */
 	get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
 
@@ -281,6 +285,7 @@ static void kexec_prepare_cpus(void)
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(0, 0);
 	local_irq_disable();
+	hard_irq_disable();
 }
 
 #endif /* SMP */
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/of_platform.c linux-libre-3.8.13-gnu1/arch/powerpc/kernel/of_platform.c
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/of_platform.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/of_platform.c	2013-05-11 16:57:46.000000000 -0400
@@ -95,6 +95,9 @@ static int of_pci_phb_probe(struct platf
 	/* Add probed PCI devices to the device model */
 	pci_bus_add_devices(phb->bus);
 
+	/* sysfs files should only be added after devices are added */
+	eeh_add_sysfs_files(phb->bus);
+
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/pci-common.c linux-libre-3.8.13-gnu1/arch/powerpc/kernel/pci-common.c
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/pci-common.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/pci-common.c	2013-05-11 16:57:46.000000000 -0400
@@ -1477,11 +1477,14 @@ void pcibios_finish_adding_to_bus(struct
 	pcibios_allocate_bus_resources(bus);
 	pcibios_claim_one_bus(bus);
 
+	/* Fixup EEH */
+	eeh_add_device_tree_late(bus);
+
 	/* Add new devices to global lists.  Register in proc, sysfs. */
 	pci_bus_add_devices(bus);
 
-	/* Fixup EEH */
-	eeh_add_device_tree_late(bus);
+	/* sysfs files should only be added after devices are added */
+	eeh_add_sysfs_files(bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
 
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/setup_64.c linux-libre-3.8.13-gnu1/arch/powerpc/kernel/setup_64.c
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/setup_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/setup_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -156,6 +156,15 @@ early_param("smt-enabled", early_smt_ena
 #define check_smt_enabled()
 #endif /* CONFIG_SMP */
 
+/** Fix up paca fields required for the boot cpu */
+static void fixup_boot_paca(void)
+{
+	/* The boot cpu is started */
+	get_paca()->cpu_start = 1;
+	/* Allow percpu accesses to work until we setup percpu data */
+	get_paca()->data_offset = 0;
+}
+
 /*
  * Early initialization entry point. This is called by head.S
  * with MMU translation disabled. We rely on the "feature" of
@@ -185,6 +194,7 @@ void __init early_setup(unsigned long dt
 	/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
 	initialise_paca(&boot_paca, 0);
 	setup_paca(&boot_paca);
+	fixup_boot_paca();
 
 	/* Initialize lockdep early or else spinlocks will blow */
 	lockdep_init();
@@ -205,11 +215,7 @@ void __init early_setup(unsigned long dt
 
 	/* Now we know the logical id of our boot cpu, setup the paca. */
 	setup_paca(&paca[boot_cpuid]);
-
-	/* Fix up paca fields required for the boot cpu */
-	get_paca()->cpu_start = 1;
-	/* Allow percpu accesses to "work" until we setup percpu data */
-	get_paca()->data_offset = 0;
+	fixup_boot_paca();
 
 	/* Probe the machine type */
 	probe_machine();
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kernel/traps.c linux-libre-3.8.13-gnu1/arch/powerpc/kernel/traps.c
--- linux-libre-3.8-gnu1/arch/powerpc/kernel/traps.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kernel/traps.c	2013-05-11 16:57:46.000000000 -0400
@@ -961,7 +961,10 @@ static int emulate_instruction(struct pt
 
 #ifdef CONFIG_PPC64
 	/* Emulate the mfspr rD, DSCR. */
-	if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) &&
+	if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) ==
+		PPC_INST_MFSPR_DSCR_USER) ||
+	     ((instword & PPC_INST_MFSPR_DSCR_MASK) ==
+		PPC_INST_MFSPR_DSCR)) &&
 			cpu_has_feature(CPU_FTR_DSCR)) {
 		PPC_WARN_EMULATED(mfdscr, regs);
 		rd = (instword >> 21) & 0x1f;
@@ -969,7 +972,10 @@ static int emulate_instruction(struct pt
 		return 0;
 	}
 	/* Emulate the mtspr DSCR, rD. */
-	if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) &&
+	if ((((instword & PPC_INST_MTSPR_DSCR_USER_MASK) ==
+		PPC_INST_MTSPR_DSCR_USER) ||
+	     ((instword & PPC_INST_MTSPR_DSCR_MASK) ==
+		PPC_INST_MTSPR_DSCR)) &&
 			cpu_has_feature(CPU_FTR_DSCR)) {
 		PPC_WARN_EMULATED(mtdscr, regs);
 		rd = (instword >> 21) & 0x1f;
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kvm/book3s_64_mmu_host.c linux-libre-3.8.13-gnu1/arch/powerpc/kvm/book3s_64_mmu_host.c
--- linux-libre-3.8-gnu1/arch/powerpc/kvm/book3s_64_mmu_host.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kvm/book3s_64_mmu_host.c	2013-05-11 16:57:46.000000000 -0400
@@ -326,8 +326,8 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcp
 	vcpu3s->context_id[0] = err;
 
 	vcpu3s->proto_vsid_max = ((vcpu3s->context_id[0] + 1)
-				  << USER_ESID_BITS) - 1;
-	vcpu3s->proto_vsid_first = vcpu3s->context_id[0] << USER_ESID_BITS;
+				  << ESID_BITS) - 1;
+	vcpu3s->proto_vsid_first = vcpu3s->context_id[0] << ESID_BITS;
 	vcpu3s->proto_vsid_next = vcpu3s->proto_vsid_first;
 
 	kvmppc_mmu_hpte_init(vcpu);
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/kvm/e500mc.c linux-libre-3.8.13-gnu1/arch/powerpc/kvm/e500mc.c
--- linux-libre-3.8-gnu1/arch/powerpc/kvm/e500mc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/kvm/e500mc.c	2013-05-11 16:57:46.000000000 -0400
@@ -108,6 +108,8 @@ void kvmppc_mmu_msr_notify(struct kvm_vc
 {
 }
 
+static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu);
+
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
@@ -136,8 +138,11 @@ void kvmppc_core_vcpu_load(struct kvm_vc
 	mtspr(SPRN_GDEAR, vcpu->arch.shared->dar);
 	mtspr(SPRN_GESR, vcpu->arch.shared->esr);
 
-	if (vcpu->arch.oldpir != mfspr(SPRN_PIR))
+	if (vcpu->arch.oldpir != mfspr(SPRN_PIR) ||
+	    __get_cpu_var(last_vcpu_on_cpu) != vcpu) {
 		kvmppc_e500_tlbil_all(vcpu_e500);
+		__get_cpu_var(last_vcpu_on_cpu) = vcpu;
+	}
 
 	kvmppc_load_guest_fp(vcpu);
 }
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/lib/Makefile linux-libre-3.8.13-gnu1/arch/powerpc/lib/Makefile
--- linux-libre-3.8-gnu1/arch/powerpc/lib/Makefile	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/lib/Makefile	2013-05-11 16:57:46.000000000 -0400
@@ -19,9 +19,7 @@ obj-$(CONFIG_PPC64)	+= copypage_64.o cop
 			   checksum_wrappers_64.o hweight_64.o \
 			   copyuser_power7.o string_64.o copypage_power7.o \
 			   memcpy_power7.o
-obj-$(CONFIG_XMON)	+= sstep.o ldstfp.o
-obj-$(CONFIG_KPROBES)	+= sstep.o ldstfp.o
-obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= sstep.o ldstfp.o
+obj-$(CONFIG_PPC_EMULATE_SSTEP)	+= sstep.o ldstfp.o
 
 ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_SMP)	+= locks.o
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/mm/hash_utils_64.c linux-libre-3.8.13-gnu1/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-3.8-gnu1/arch/powerpc/mm/hash_utils_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/mm/hash_utils_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -194,6 +194,11 @@ int htab_bolt_mapping(unsigned long vsta
 		unsigned long vpn  = hpt_vpn(vaddr, vsid, ssize);
 		unsigned long tprot = prot;
 
+		/*
+		 * If we hit a bad address return error.
+		 */
+		if (!vsid)
+			return -1;
 		/* Make kernel text executable */
 		if (overlaps_kernel_text(vaddr, vaddr + step))
 			tprot &= ~HPTE_R_N;
@@ -758,6 +763,8 @@ void __init early_init_mmu(void)
 	/* Initialize stab / SLB management */
 	if (mmu_has_feature(MMU_FTR_SLB))
 		slb_initialize();
+	else
+		stab_initialize(get_paca()->stab_real);
 }
 
 #ifdef CONFIG_SMP
@@ -921,11 +928,6 @@ int hash_page(unsigned long ea, unsigned
 	DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
 		ea, access, trap);
 
-	if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) {
-		DBG_LOW(" out of pgtable range !\n");
- 		return 1;
-	}
-
 	/* Get region & vsid */
  	switch (REGION_ID(ea)) {
 	case USER_REGION_ID:
@@ -956,6 +958,11 @@ int hash_page(unsigned long ea, unsigned
 	}
 	DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
 
+	/* Bad address. */
+	if (!vsid) {
+		DBG_LOW("Bad address!\n");
+		return 1;
+	}
 	/* Get pgdir */
 	pgdir = mm->pgd;
 	if (pgdir == NULL)
@@ -1125,6 +1132,8 @@ void hash_preload(struct mm_struct *mm,
 	/* Get VSID */
 	ssize = user_segment_size(ea);
 	vsid = get_vsid(mm->context.id, ea, ssize);
+	if (!vsid)
+		return;
 
 	/* Hash doesn't like irqs */
 	local_irq_save(flags);
@@ -1217,6 +1226,9 @@ static void kernel_map_linear_page(unsig
 	hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
 	hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
+	/* Don't create HPTE entries for bad address */
+	if (!vsid)
+		return;
 	ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr),
 				 mode, HPTE_V_BOLTED,
 				 mmu_linear_psize, mmu_kernel_ssize);
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/mm/mmu_context_hash64.c linux-libre-3.8.13-gnu1/arch/powerpc/mm/mmu_context_hash64.c
--- linux-libre-3.8-gnu1/arch/powerpc/mm/mmu_context_hash64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/mm/mmu_context_hash64.c	2013-05-11 16:57:46.000000000 -0400
@@ -29,15 +29,6 @@
 static DEFINE_SPINLOCK(mmu_context_lock);
 static DEFINE_IDA(mmu_context_ida);
 
-/*
- * 256MB segment
- * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
- * available for user mappings. Each segment contains 2^28 bytes. Each
- * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
- * (19 == 37 + 28 - 46).
- */
-#define MAX_CONTEXT	((1UL << CONTEXT_BITS) - 1)
-
 int __init_new_context(void)
 {
 	int index;
@@ -56,7 +47,7 @@ again:
 	else if (err)
 		return err;
 
-	if (index > MAX_CONTEXT) {
+	if (index > MAX_USER_CONTEXT) {
 		spin_lock(&mmu_context_lock);
 		ida_remove(&mmu_context_ida, index);
 		spin_unlock(&mmu_context_lock);
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/mm/numa.c linux-libre-3.8.13-gnu1/arch/powerpc/mm/numa.c
--- linux-libre-3.8-gnu1/arch/powerpc/mm/numa.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/mm/numa.c	2013-05-11 16:57:46.000000000 -0400
@@ -201,7 +201,7 @@ int __node_distance(int a, int b)
 	int distance = LOCAL_DISTANCE;
 
 	if (!form1_affinity)
-		return distance;
+		return ((a == b) ? LOCAL_DISTANCE : REMOTE_DISTANCE);
 
 	for (i = 0; i < distance_ref_points_depth; i++) {
 		if (distance_lookup_table[a][i] == distance_lookup_table[b][i])
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/mm/pgtable_64.c linux-libre-3.8.13-gnu1/arch/powerpc/mm/pgtable_64.c
--- linux-libre-3.8-gnu1/arch/powerpc/mm/pgtable_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/mm/pgtable_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,7 +61,7 @@
 #endif
 
 #ifdef CONFIG_PPC_STD_MMU_64
-#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#if TASK_SIZE_USER64 > (1UL << (ESID_BITS + SID_SHIFT))
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 #endif
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/mm/slb_low.S linux-libre-3.8.13-gnu1/arch/powerpc/mm/slb_low.S
--- linux-libre-3.8-gnu1/arch/powerpc/mm/slb_low.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/mm/slb_low.S	2013-05-11 16:57:46.000000000 -0400
@@ -31,10 +31,15 @@
  * No other registers are examined or changed.
  */
 _GLOBAL(slb_allocate_realmode)
-	/* r3 = faulting address */
+	/*
+	 * check for bad kernel/user address
+	 * (ea & ~REGION_MASK) >= PGTABLE_RANGE
+	 */
+	rldicr. r9,r3,4,(63 - 46 - 4)
+	bne-	8f
 
 	srdi	r9,r3,60		/* get region */
-	srdi	r10,r3,28		/* get esid */
+	srdi	r10,r3,SID_SHIFT	/* get esid */
 	cmpldi	cr7,r9,0xc		/* cmp PAGE_OFFSET for later use */
 
 	/* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */
@@ -56,12 +61,14 @@ _GLOBAL(slb_allocate_realmode)
 	 */
 _GLOBAL(slb_miss_kernel_load_linear)
 	li	r11,0
-	li	r9,0x1
 	/*
-	 * for 1T we shift 12 bits more.  slb_finish_load_1T will do
-	 * the necessary adjustment
+	 * context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
+	 * r9 = region id.
 	 */
-	rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
+	addis	r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha
+	addi	r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
+
+
 BEGIN_FTR_SECTION
 	b	slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -91,24 +98,19 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
 	_GLOBAL(slb_miss_kernel_load_io)
 	li	r11,0
 6:
-	li	r9,0x1
 	/*
-	 * for 1T we shift 12 bits more.  slb_finish_load_1T will do
-	 * the necessary adjustment
+	 * context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
+	 * r9 = region id.
 	 */
-	rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
+	addis	r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha
+	addi	r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
+
 BEGIN_FTR_SECTION
 	b	slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
 	b	slb_finish_load_1T
 
-0:	/* user address: proto-VSID = context << 15 | ESID. First check
-	 * if the address is within the boundaries of the user region
-	 */
-	srdi.	r9,r10,USER_ESID_BITS
-	bne-	8f			/* invalid ea bits set */
-
-
+0:
 	/* when using slices, we extract the psize off the slice bitmaps
 	 * and then we need to get the sllp encoding off the mmu_psize_defs
 	 * array.
@@ -164,15 +166,13 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEG
 	ld	r9,PACACONTEXTID(r13)
 BEGIN_FTR_SECTION
 	cmpldi	r10,0x1000
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	rldimi	r10,r9,USER_ESID_BITS,0
-BEGIN_FTR_SECTION
 	bge	slb_finish_load_1T
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	b	slb_finish_load
 
 8:	/* invalid EA */
 	li	r10,0			/* BAD_VSID */
+	li	r9,0			/* BAD_VSID */
 	li	r11,SLB_VSID_USER	/* flags don't much matter */
 	b	slb_finish_load
 
@@ -221,8 +221,6 @@ _GLOBAL(slb_allocate_user)
 
 	/* get context to calculate proto-VSID */
 	ld	r9,PACACONTEXTID(r13)
-	rldimi	r10,r9,USER_ESID_BITS,0
-
 	/* fall through slb_finish_load */
 
 #endif /* __DISABLED__ */
@@ -231,9 +229,10 @@ _GLOBAL(slb_allocate_user)
 /*
  * Finish loading of an SLB entry and return
  *
- * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
+ * r3 = EA, r9 = context, r10 = ESID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
  */
 slb_finish_load:
+	rldimi  r10,r9,ESID_BITS,0
 	ASM_VSID_SCRAMBLE(r10,r9,256M)
 	/*
 	 * bits above VSID_BITS_256M need to be ignored from r10
@@ -298,10 +297,11 @@ _GLOBAL(slb_compare_rr_to_size)
 /*
  * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return.
  *
- * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9
+ * r3 = EA, r9 = context, r10 = ESID(256MB), r11 = flags, clobbers r9
  */
 slb_finish_load_1T:
-	srdi	r10,r10,40-28		/* get 1T ESID */
+	srdi	r10,r10,(SID_SHIFT_1T - SID_SHIFT)	/* get 1T ESID */
+	rldimi  r10,r9,ESID_BITS_1T,0
 	ASM_VSID_SCRAMBLE(r10,r9,1T)
 	/*
 	 * bits above VSID_BITS_1T need to be ignored from r10
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/mm/tlb_hash64.c linux-libre-3.8.13-gnu1/arch/powerpc/mm/tlb_hash64.c
--- linux-libre-3.8-gnu1/arch/powerpc/mm/tlb_hash64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/mm/tlb_hash64.c	2013-05-11 16:57:46.000000000 -0400
@@ -82,11 +82,11 @@ void hpte_need_flush(struct mm_struct *m
 	if (!is_kernel_addr(addr)) {
 		ssize = user_segment_size(addr);
 		vsid = get_vsid(mm->context.id, addr, ssize);
-		WARN_ON(vsid == 0);
 	} else {
 		vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
 		ssize = mmu_kernel_ssize;
 	}
+	WARN_ON(vsid == 0);
 	vpn = hpt_vpn(addr, vsid, ssize);
 	rpte = __real_pte(__pte(pte), ptep);
 
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/platforms/cell/spufs/inode.c linux-libre-3.8.13-gnu1/arch/powerpc/platforms/cell/spufs/inode.c
--- linux-libre-3.8-gnu1/arch/powerpc/platforms/cell/spufs/inode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/platforms/cell/spufs/inode.c	2013-05-11 16:57:46.000000000 -0400
@@ -99,6 +99,7 @@ spufs_new_inode(struct super_block *sb,
 	if (!inode)
 		goto out;
 
+	inode->i_ino = get_next_ino();
 	inode->i_mode = mode;
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/platforms/pseries/eeh.c linux-libre-3.8.13-gnu1/arch/powerpc/platforms/pseries/eeh.c
--- linux-libre-3.8-gnu1/arch/powerpc/platforms/pseries/eeh.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/platforms/pseries/eeh.c	2013-05-11 16:57:46.000000000 -0400
@@ -788,7 +788,6 @@ static void eeh_add_device_late(struct p
 	dev->dev.archdata.edev = edev;
 
 	eeh_addr_cache_insert_dev(dev);
-	eeh_sysfs_add_device(dev);
 }
 
 /**
@@ -815,6 +814,29 @@ void eeh_add_device_tree_late(struct pci
 EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
 
 /**
+ * eeh_add_sysfs_files - Add EEH sysfs files for the indicated PCI bus
+ * @bus: PCI bus
+ *
+ * This routine must be used to add EEH sysfs files for PCI
+ * devices which are attached to the indicated PCI bus. The PCI bus
+ * is added after system boot through hotplug or dlpar.
+ */
+void eeh_add_sysfs_files(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		eeh_sysfs_add_device(dev);
+		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+			struct pci_bus *subbus = dev->subordinate;
+			if (subbus)
+				eeh_add_sysfs_files(subbus);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(eeh_add_sysfs_files);
+
+/**
  * eeh_remove_device - Undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
  * @purge_pe: remove the PE or not
diff -druNp linux-libre-3.8-gnu1/arch/powerpc/platforms/pseries/lpar.c linux-libre-3.8.13-gnu1/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-3.8-gnu1/arch/powerpc/platforms/pseries/lpar.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/powerpc/platforms/pseries/lpar.c	2013-05-11 16:57:46.000000000 -0400
@@ -186,7 +186,13 @@ static long pSeries_lpar_hpte_remove(uns
 					   (0x1UL << 4), &dummy1, &dummy2);
 		if (lpar_rc == H_SUCCESS)
 			return i;
-		BUG_ON(lpar_rc != H_NOT_FOUND);
+
+		/*
+		 * The test for adjunct partition is performed before the
+		 * ANDCOND test.  H_RESOURCE may be returned, so we need to
+		 * check for that as well.
+		 */
+		BUG_ON(lpar_rc != H_NOT_FOUND && lpar_rc != H_RESOURCE);
 
 		slot_offset++;
 		slot_offset &= 0x7;
diff -druNp linux-libre-3.8-gnu1/arch/s390/include/asm/io.h linux-libre-3.8.13-gnu1/arch/s390/include/asm/io.h
--- linux-libre-3.8-gnu1/arch/s390/include/asm/io.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/include/asm/io.h	2013-05-11 16:57:46.000000000 -0400
@@ -50,10 +50,6 @@ void unxlate_dev_mem_ptr(unsigned long p
 #define ioremap_nocache(addr, size)	ioremap(addr, size)
 #define ioremap_wc			ioremap_nocache
 
-/* TODO: s390 cannot support io_remap_pfn_range... */
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) 	       \
-	remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 {
 	return (void __iomem *) offset;
diff -druNp linux-libre-3.8-gnu1/arch/s390/include/asm/pgtable.h linux-libre-3.8.13-gnu1/arch/s390/include/asm/pgtable.h
--- linux-libre-3.8-gnu1/arch/s390/include/asm/pgtable.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/include/asm/pgtable.h	2013-05-11 16:57:46.000000000 -0400
@@ -56,6 +56,10 @@ extern unsigned long zero_page_mask;
 	 (((unsigned long)(vaddr)) &zero_page_mask))))
 #define __HAVE_COLOR_ZERO_PAGE
 
+/* TODO: s390 cannot support io_remap_pfn_range... */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) 	       \
+	remap_pfn_range(vma, vaddr, pfn, size, prot)
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff -druNp linux-libre-3.8-gnu1/arch/s390/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/s390/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/s390/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -34,6 +34,7 @@ struct sigaction {
         void (*sa_restorer)(void);
         sigset_t sa_mask;               /* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
         struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/arch/s390/include/asm/tlbflush.h linux-libre-3.8.13-gnu1/arch/s390/include/asm/tlbflush.h
--- linux-libre-3.8-gnu1/arch/s390/include/asm/tlbflush.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/include/asm/tlbflush.h	2013-05-11 16:57:46.000000000 -0400
@@ -74,8 +74,6 @@ static inline void __tlb_flush_idte(unsi
 
 static inline void __tlb_flush_mm(struct mm_struct * mm)
 {
-	if (unlikely(cpumask_empty(mm_cpumask(mm))))
-		return;
 	/*
 	 * If the machine has IDTE we prefer to do a per mm flush
 	 * on all cpus instead of doing a local flush if the mm
diff -druNp linux-libre-3.8-gnu1/arch/s390/kernel/entry64.S linux-libre-3.8.13-gnu1/arch/s390/kernel/entry64.S
--- linux-libre-3.8-gnu1/arch/s390/kernel/entry64.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/kernel/entry64.S	2013-05-11 16:57:46.000000000 -0400
@@ -678,8 +678,9 @@ ENTRY(mcck_int_handler)
 	UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER
 	LAST_BREAK %r14
 mcck_skip:
-	lghi	%r14,__LC_GPREGS_SAVE_AREA
-	mvc	__PT_R0(128,%r11),0(%r14)
+	lghi	%r14,__LC_GPREGS_SAVE_AREA+64
+	stmg	%r0,%r7,__PT_R0(%r11)
+	mvc	__PT_R8(64,%r11),0(%r14)
 	stmg	%r8,%r9,__PT_PSW(%r11)
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 	lgr	%r2,%r11		# pass pointer to pt_regs
diff -druNp linux-libre-3.8-gnu1/arch/s390/kernel/entry.S linux-libre-3.8.13-gnu1/arch/s390/kernel/entry.S
--- linux-libre-3.8-gnu1/arch/s390/kernel/entry.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/kernel/entry.S	2013-05-11 16:57:46.000000000 -0400
@@ -636,7 +636,8 @@ ENTRY(mcck_int_handler)
 	UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER
 mcck_skip:
 	SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT
-	mvc	__PT_R0(64,%r11),__LC_GPREGS_SAVE_AREA
+	stm	%r0,%r7,__PT_R0(%r11)
+	mvc	__PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32
 	stm	%r8,%r9,__PT_PSW(%r11)
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
 	l	%r1,BASED(.Ldo_machine_check)
diff -druNp linux-libre-3.8-gnu1/arch/s390/kvm/kvm-s390.c linux-libre-3.8.13-gnu1/arch/s390/kvm/kvm-s390.c
--- linux-libre-3.8-gnu1/arch/s390/kvm/kvm-s390.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/s390/kvm/kvm-s390.c	2013-05-11 16:57:46.000000000 -0400
@@ -766,6 +766,14 @@ int kvm_s390_vcpu_store_status(struct kv
 	} else
 		prefix = 0;
 
+	/*
+	 * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy
+	 * copying in vcpu load/put. Lets update our copies before we save
+	 * it into the save area
+	 */
+	save_fp_regs(&vcpu->arch.guest_fpregs);
+	save_access_regs(vcpu->run->s.regs.acrs);
+
 	if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
 			vcpu->arch.guest_fpregs.fprs, 128, prefix))
 		return -EFAULT;
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/hugetlb.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/hugetlb.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/hugetlb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/hugetlb.h	2013-05-11 16:57:46.000000000 -0400
@@ -12,7 +12,6 @@ pte_t huge_ptep_get_and_clear(struct mm_
 
 static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
 {
-	hugetlb_setup(mm);
 }
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/page_64.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/page_64.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/page_64.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/page_64.h	2013-05-11 16:57:46.000000000 -0400
@@ -27,8 +27,8 @@
 #ifndef __ASSEMBLY__
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-struct mm_struct;
-extern void hugetlb_setup(struct mm_struct *mm);
+struct pt_regs;
+extern void hugetlb_setup(struct pt_regs *regs);
 #endif
 
 #define WANT_PAGE_VIRTUAL
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/pgtable_64.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/pgtable_64.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/pgtable_64.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/pgtable_64.h	2013-05-11 16:57:46.000000000 -0400
@@ -915,6 +915,7 @@ static inline int io_remap_pfn_range(str
 	return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
 }
 
+#include <asm/tlbflush.h>
 #include <asm-generic/pgtable.h>
 
 /* We provide our own get_unmapped_area to cope with VA holes and
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -26,5 +26,7 @@ struct k_sigaction {
 	void			__user *ka_restorer;
 };
 
+#define __ARCH_HAS_SA_RESTORER
+
 #endif /* !(__ASSEMBLY__) */
 #endif /* !(__SPARC_SIGNAL_H) */
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/switch_to_64.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/switch_to_64.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/switch_to_64.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/switch_to_64.h	2013-05-11 16:57:46.000000000 -0400
@@ -18,8 +18,7 @@ do {						\
 	 * and 2 stores in this critical code path.  -DaveM
 	 */
 #define switch_to(prev, next, last)					\
-do {	flush_tlb_pending();						\
-	save_and_clear_fpu();						\
+do {	save_and_clear_fpu();						\
 	/* If you are tempted to conditionalize the following */	\
 	/* so that ASI is only written if it changes, think again. */	\
 	__asm__ __volatile__("wr %%g0, %0, %%asi"			\
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/tlbflush_64.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/tlbflush_64.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/tlbflush_64.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/tlbflush_64.h	2013-05-11 16:57:46.000000000 -0400
@@ -11,24 +11,40 @@
 struct tlb_batch {
 	struct mm_struct *mm;
 	unsigned long tlb_nr;
+	unsigned long active;
 	unsigned long vaddrs[TLB_BATCH_NR];
 };
 
 extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
 extern void flush_tsb_user(struct tlb_batch *tb);
+extern void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
 
 /* TLB flush operations. */
 
-extern void flush_tlb_pending(void);
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+}
 
-#define flush_tlb_range(vma,start,end)	\
-	do { (void)(start); flush_tlb_pending(); } while (0)
-#define flush_tlb_page(vma,addr)	flush_tlb_pending()
-#define flush_tlb_mm(mm)		flush_tlb_pending()
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+}
+
+#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+
+extern void flush_tlb_pending(void);
+extern void arch_enter_lazy_mmu_mode(void);
+extern void arch_leave_lazy_mmu_mode(void);
+#define arch_flush_lazy_mmu_mode()      do {} while (0)
 
 /* Local cpu only.  */
 extern void __flush_tlb_all(void);
-
+extern void __flush_tlb_page(unsigned long context, unsigned long vaddr);
 extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
 
 #ifndef CONFIG_SMP
@@ -38,15 +54,24 @@ do {	flush_tsb_kernel_range(start,end);
 	__flush_tlb_kernel_range(start,end); \
 } while (0)
 
+static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+	__flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
+}
+
 #else /* CONFIG_SMP */
 
 extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
 
 #define flush_tlb_kernel_range(start, end) \
 do {	flush_tsb_kernel_range(start,end); \
 	smp_flush_tlb_kernel_range(start, end); \
 } while (0)
 
+#define global_flush_tlb_page(mm, vaddr) \
+	smp_flush_tlb_page(mm, vaddr)
+
 #endif /* ! CONFIG_SMP */
 
 #endif /* _SPARC64_TLBFLUSH_H */
diff -druNp linux-libre-3.8-gnu1/arch/sparc/include/asm/tsb.h linux-libre-3.8.13-gnu1/arch/sparc/include/asm/tsb.h
--- linux-libre-3.8-gnu1/arch/sparc/include/asm/tsb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/include/asm/tsb.h	2013-05-11 16:57:46.000000000 -0400
@@ -157,17 +157,26 @@ extern struct tsb_phys_patch_entry __tsb
 	andn		REG2, 0x7, REG2; \
 	add		REG1, REG2, REG1;
 
-	/* This macro exists only to make the PMD translator below easier
-	 * to read.  It hides the ELF section switch for the sun4v code
-	 * patching.
+	/* These macros exists only to make the PMD translator below
+	 * easier to read.  It hides the ELF section switch for the
+	 * sun4v code patching.
 	 */
-#define OR_PTE_BIT(REG, NAME)				\
+#define OR_PTE_BIT_1INSN(REG, NAME)			\
 661:	or		REG, _PAGE_##NAME##_4U, REG;	\
 	.section	.sun4v_1insn_patch, "ax";	\
 	.word		661b;				\
 	or		REG, _PAGE_##NAME##_4V, REG;	\
 	.previous;
 
+#define OR_PTE_BIT_2INSN(REG, TMP, NAME)		\
+661:	sethi		%hi(_PAGE_##NAME##_4U), TMP;	\
+	or		REG, TMP, REG;			\
+	.section	.sun4v_2insn_patch, "ax";	\
+	.word		661b;				\
+	mov		-1, TMP;			\
+	or		REG, _PAGE_##NAME##_4V, REG;	\
+	.previous;
+
 	/* Load into REG the PTE value for VALID, CACHE, and SZHUGE.  */
 #define BUILD_PTE_VALID_SZHUGE_CACHE(REG)				   \
 661:	sethi		%uhi(_PAGE_VALID|_PAGE_SZHUGE_4U), REG;		   \
@@ -214,12 +223,13 @@ extern struct tsb_phys_patch_entry __tsb
 	 andn		REG1, PMD_HUGE_PROTBITS, REG2;			      \
 	sllx		REG2, PMD_PADDR_SHIFT, REG2;			      \
 	/* REG2 now holds PFN << PAGE_SHIFT */				      \
-	andcc		REG1, PMD_HUGE_EXEC, %g0;			      \
-	bne,a,pt	%xcc, 1f;					      \
-	 OR_PTE_BIT(REG2, EXEC);					      \
-1:	andcc		REG1, PMD_HUGE_WRITE, %g0;			      \
+	andcc		REG1, PMD_HUGE_WRITE, %g0;			      \
 	bne,a,pt	%xcc, 1f;					      \
-	 OR_PTE_BIT(REG2, W);						      \
+	 OR_PTE_BIT_1INSN(REG2, W);					      \
+1:	andcc		REG1, PMD_HUGE_EXEC, %g0;			      \
+	be,pt		%xcc, 1f;					      \
+	 nop;								      \
+	OR_PTE_BIT_2INSN(REG2, REG1, EXEC);				      \
 	/* REG1 can now be clobbered, build final PTE */		      \
 1:	BUILD_PTE_VALID_SZHUGE_CACHE(REG1);				      \
 	ba,pt		%xcc, PTE_LABEL;				      \
diff -druNp linux-libre-3.8-gnu1/arch/sparc/kernel/smp_64.c linux-libre-3.8.13-gnu1/arch/sparc/kernel/smp_64.c
--- linux-libre-3.8-gnu1/arch/sparc/kernel/smp_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/kernel/smp_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -849,7 +849,7 @@ void smp_tsb_sync(struct mm_struct *mm)
 }
 
 extern unsigned long xcall_flush_tlb_mm;
-extern unsigned long xcall_flush_tlb_pending;
+extern unsigned long xcall_flush_tlb_page;
 extern unsigned long xcall_flush_tlb_kernel_range;
 extern unsigned long xcall_fetch_glob_regs;
 extern unsigned long xcall_fetch_glob_pmu;
@@ -1074,22 +1074,55 @@ local_flush_and_out:
 	put_cpu();
 }
 
+struct tlb_pending_info {
+	unsigned long ctx;
+	unsigned long nr;
+	unsigned long *vaddrs;
+};
+
+static void tlb_pending_func(void *info)
+{
+	struct tlb_pending_info *t = info;
+
+	__flush_tlb_pending(t->ctx, t->nr, t->vaddrs);
+}
+
 void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs)
 {
 	u32 ctx = CTX_HWBITS(mm->context);
+	struct tlb_pending_info info;
 	int cpu = get_cpu();
 
+	info.ctx = ctx;
+	info.nr = nr;
+	info.vaddrs = vaddrs;
+
 	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
 		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
 	else
-		smp_cross_call_masked(&xcall_flush_tlb_pending,
-				      ctx, nr, (unsigned long) vaddrs,
-				      mm_cpumask(mm));
+		smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
+				       &info, 1);
 
 	__flush_tlb_pending(ctx, nr, vaddrs);
 
 	put_cpu();
 }
+
+void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+	unsigned long context = CTX_HWBITS(mm->context);
+	int cpu = get_cpu();
+
+	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
+		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
+	else
+		smp_cross_call_masked(&xcall_flush_tlb_page,
+				      context, vaddr, 0,
+				      mm_cpumask(mm));
+	__flush_tlb_page(context, vaddr);
+
+	put_cpu();
+}
 
 void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
diff -druNp linux-libre-3.8-gnu1/arch/sparc/kernel/tsb.S linux-libre-3.8.13-gnu1/arch/sparc/kernel/tsb.S
--- linux-libre-3.8-gnu1/arch/sparc/kernel/tsb.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/kernel/tsb.S	2013-05-11 16:57:46.000000000 -0400
@@ -136,12 +136,43 @@ tsb_miss_page_table_walk_sun4v_fastpath:
 	 nop
 
 	/* It is a huge page, use huge page TSB entry address we
-	 * calculated above.
+	 * calculated above.  If the huge page TSB has not been
+	 * allocated, setup a trap stack and call hugetlb_setup()
+	 * to do so, then return from the trap to replay the TLB
+	 * miss.
+	 *
+	 * This is necessary to handle the case of transparent huge
+	 * pages where we don't really have a non-atomic context
+	 * in which to allocate the hugepage TSB hash table.  When
+	 * the 'mm' faults in the hugepage for the first time, we
+	 * thus handle it here.  This also makes sure that we can
+	 * allocate the TSB hash table on the correct NUMA node.
 	 */
 	TRAP_LOAD_TRAP_BLOCK(%g7, %g2)
-	ldx		[%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP], %g2
-	cmp		%g2, -1
-	movne		%xcc, %g2, %g1
+	ldx		[%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP], %g1
+	cmp		%g1, -1
+	bne,pt		%xcc, 60f
+	 nop
+
+661:	rdpr		%pstate, %g5
+	wrpr		%g5, PSTATE_AG | PSTATE_MG, %pstate
+	.section	.sun4v_2insn_patch, "ax"
+	.word		661b
+	SET_GL(1)
+	nop
+	.previous
+
+	rdpr	%tl, %g3
+	cmp	%g3, 1
+	bne,pn	%xcc, winfix_trampoline
+	 nop
+	ba,pt	%xcc, etrap
+	 rd	%pc, %g7
+	call	hugetlb_setup
+	 add	%sp, PTREGS_OFF, %o0
+	ba,pt	%xcc, rtrap
+	 nop
+
 60:
 #endif
 
diff -druNp linux-libre-3.8-gnu1/arch/sparc/mm/fault_64.c linux-libre-3.8.13-gnu1/arch/sparc/mm/fault_64.c
--- linux-libre-3.8-gnu1/arch/sparc/mm/fault_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/mm/fault_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -472,8 +472,13 @@ good_area:
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
 	mm_rss = mm->context.huge_pte_count;
 	if (unlikely(mm_rss >
-		     mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit))
-		tsb_grow(mm, MM_TSB_HUGE, mm_rss);
+		     mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) {
+		if (mm->context.tsb_block[MM_TSB_HUGE].tsb)
+			tsb_grow(mm, MM_TSB_HUGE, mm_rss);
+		else
+			hugetlb_setup(regs);
+
+	}
 #endif
 	return;
 
diff -druNp linux-libre-3.8-gnu1/arch/sparc/mm/init_64.c linux-libre-3.8.13-gnu1/arch/sparc/mm/init_64.c
--- linux-libre-3.8-gnu1/arch/sparc/mm/init_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/mm/init_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -314,16 +314,31 @@ static void __update_mmu_tsb_insert(stru
 	struct tsb *tsb = mm->context.tsb_block[tsb_index].tsb;
 	unsigned long tag;
 
+	if (unlikely(!tsb))
+		return;
+
 	tsb += ((address >> tsb_hash_shift) &
 		(mm->context.tsb_block[tsb_index].tsb_nentries - 1UL));
 	tag = (address >> 22UL);
 	tsb_insert(tsb, tag, tte);
 }
 
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+	if ((tlb_type == hypervisor &&
+	     (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
+	    (tlb_type != hypervisor &&
+	     (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U))
+		return true;
+	return false;
+}
+#endif
+
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
-	unsigned long tsb_index, tsb_hash_shift, flags;
 	struct mm_struct *mm;
+	unsigned long flags;
 	pte_t pte = *ptep;
 
 	if (tlb_type != hypervisor) {
@@ -335,25 +350,16 @@ void update_mmu_cache(struct vm_area_str
 
 	mm = vma->vm_mm;
 
-	tsb_index = MM_TSB_BASE;
-	tsb_hash_shift = PAGE_SHIFT;
-
 	spin_lock_irqsave(&mm->context.lock, flags);
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (mm->context.tsb_block[MM_TSB_HUGE].tsb != NULL) {
-		if ((tlb_type == hypervisor &&
-		     (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
-		    (tlb_type != hypervisor &&
-		     (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U)) {
-			tsb_index = MM_TSB_HUGE;
-			tsb_hash_shift = HPAGE_SHIFT;
-		}
-	}
+	if (mm->context.huge_pte_count && is_hugetlb_pte(pte))
+		__update_mmu_tsb_insert(mm, MM_TSB_HUGE, HPAGE_SHIFT,
+					address, pte_val(pte));
+	else
 #endif
-
-	__update_mmu_tsb_insert(mm, tsb_index, tsb_hash_shift,
-				address, pte_val(pte));
+		__update_mmu_tsb_insert(mm, MM_TSB_BASE, PAGE_SHIFT,
+					address, pte_val(pte));
 
 	spin_unlock_irqrestore(&mm->context.lock, flags);
 }
@@ -2712,14 +2718,28 @@ static void context_reload(void *__data)
 		load_secondary_context(mm);
 }
 
-void hugetlb_setup(struct mm_struct *mm)
+void hugetlb_setup(struct pt_regs *regs)
 {
-	struct tsb_config *tp = &mm->context.tsb_block[MM_TSB_HUGE];
+	struct mm_struct *mm = current->mm;
+	struct tsb_config *tp;
 
-	if (likely(tp->tsb != NULL))
-		return;
+	if (in_atomic() || !mm) {
+		const struct exception_table_entry *entry;
+
+		entry = search_exception_tables(regs->tpc);
+		if (entry) {
+			regs->tpc = entry->fixup;
+			regs->tnpc = regs->tpc + 4;
+			return;
+		}
+		pr_alert("Unexpected HugeTLB setup in atomic context.\n");
+		die_if_kernel("HugeTSB in atomic", regs);
+	}
+
+	tp = &mm->context.tsb_block[MM_TSB_HUGE];
+	if (likely(tp->tsb == NULL))
+		tsb_grow(mm, MM_TSB_HUGE, 0);
 
-	tsb_grow(mm, MM_TSB_HUGE, 0);
 	tsb_context_switch(mm);
 	smp_tsb_sync(mm);
 
diff -druNp linux-libre-3.8-gnu1/arch/sparc/mm/tlb.c linux-libre-3.8.13-gnu1/arch/sparc/mm/tlb.c
--- linux-libre-3.8-gnu1/arch/sparc/mm/tlb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/mm/tlb.c	2013-05-11 16:57:46.000000000 -0400
@@ -24,11 +24,17 @@ static DEFINE_PER_CPU(struct tlb_batch,
 void flush_tlb_pending(void)
 {
 	struct tlb_batch *tb = &get_cpu_var(tlb_batch);
+	struct mm_struct *mm = tb->mm;
 
-	if (tb->tlb_nr) {
-		flush_tsb_user(tb);
+	if (!tb->tlb_nr)
+		goto out;
 
-		if (CTX_VALID(tb->mm->context)) {
+	flush_tsb_user(tb);
+
+	if (CTX_VALID(mm->context)) {
+		if (tb->tlb_nr == 1) {
+			global_flush_tlb_page(mm, tb->vaddrs[0]);
+		} else {
 #ifdef CONFIG_SMP
 			smp_flush_tlb_pending(tb->mm, tb->tlb_nr,
 					      &tb->vaddrs[0]);
@@ -37,12 +43,30 @@ void flush_tlb_pending(void)
 					    tb->tlb_nr, &tb->vaddrs[0]);
 #endif
 		}
-		tb->tlb_nr = 0;
 	}
 
+	tb->tlb_nr = 0;
+
+out:
 	put_cpu_var(tlb_batch);
 }
 
+void arch_enter_lazy_mmu_mode(void)
+{
+	struct tlb_batch *tb = &__get_cpu_var(tlb_batch);
+
+	tb->active = 1;
+}
+
+void arch_leave_lazy_mmu_mode(void)
+{
+	struct tlb_batch *tb = &__get_cpu_var(tlb_batch);
+
+	if (tb->tlb_nr)
+		flush_tlb_pending();
+	tb->active = 0;
+}
+
 static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
 			      bool exec)
 {
@@ -60,6 +84,12 @@ static void tlb_batch_add_one(struct mm_
 		nr = 0;
 	}
 
+	if (!tb->active) {
+		global_flush_tlb_page(mm, vaddr);
+		flush_tsb_user_page(mm, vaddr);
+		goto out;
+	}
+
 	if (nr == 0)
 		tb->mm = mm;
 
@@ -68,6 +98,7 @@ static void tlb_batch_add_one(struct mm_
 	if (nr >= TLB_BATCH_NR)
 		flush_tlb_pending();
 
+out:
 	put_cpu_var(tlb_batch);
 }
 
@@ -135,8 +166,15 @@ void set_pmd_at(struct mm_struct *mm, un
 			mm->context.huge_pte_count++;
 		else
 			mm->context.huge_pte_count--;
-		if (mm->context.huge_pte_count == 1)
-			hugetlb_setup(mm);
+
+		/* Do not try to allocate the TSB hash table if we
+		 * don't have one already.  We have various locks held
+		 * and thus we'll end up doing a GFP_KERNEL allocation
+		 * in an atomic context.
+		 *
+		 * Instead, we let the first TLB miss on a hugepage
+		 * take care of this.
+		 */
 	}
 
 	if (!pmd_none(orig)) {
diff -druNp linux-libre-3.8-gnu1/arch/sparc/mm/tsb.c linux-libre-3.8.13-gnu1/arch/sparc/mm/tsb.c
--- linux-libre-3.8-gnu1/arch/sparc/mm/tsb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/mm/tsb.c	2013-05-11 16:57:46.000000000 -0400
@@ -7,11 +7,10 @@
 #include <linux/preempt.h>
 #include <linux/slab.h>
 #include <asm/page.h>
-#include <asm/tlbflush.h>
-#include <asm/tlb.h>
-#include <asm/mmu_context.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 #include <asm/tsb.h>
+#include <asm/tlb.h>
 #include <asm/oplib.h>
 
 extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
@@ -46,23 +45,27 @@ void flush_tsb_kernel_range(unsigned lon
 	}
 }
 
-static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift,
-			    unsigned long tsb, unsigned long nentries)
+static void __flush_tsb_one_entry(unsigned long tsb, unsigned long v,
+				  unsigned long hash_shift,
+				  unsigned long nentries)
 {
-	unsigned long i;
+	unsigned long tag, ent, hash;
 
-	for (i = 0; i < tb->tlb_nr; i++) {
-		unsigned long v = tb->vaddrs[i];
-		unsigned long tag, ent, hash;
+	v &= ~0x1UL;
+	hash = tsb_hash(v, hash_shift, nentries);
+	ent = tsb + (hash * sizeof(struct tsb));
+	tag = (v >> 22UL);
 
-		v &= ~0x1UL;
+	tsb_flush(ent, tag);
+}
 
-		hash = tsb_hash(v, hash_shift, nentries);
-		ent = tsb + (hash * sizeof(struct tsb));
-		tag = (v >> 22UL);
+static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift,
+			    unsigned long tsb, unsigned long nentries)
+{
+	unsigned long i;
 
-		tsb_flush(ent, tag);
-	}
+	for (i = 0; i < tb->tlb_nr; i++)
+		__flush_tsb_one_entry(tsb, tb->vaddrs[i], hash_shift, nentries);
 }
 
 void flush_tsb_user(struct tlb_batch *tb)
@@ -90,6 +93,30 @@ void flush_tsb_user(struct tlb_batch *tb
 	spin_unlock_irqrestore(&mm->context.lock, flags);
 }
 
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
+{
+	unsigned long nentries, base, flags;
+
+	spin_lock_irqsave(&mm->context.lock, flags);
+
+	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+		base = __pa(base);
+	__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
+		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+			base = __pa(base);
+		__flush_tsb_one_entry(base, vaddr, HPAGE_SHIFT, nentries);
+	}
+#endif
+	spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
 #define HV_PGSZ_IDX_BASE	HV_PGSZ_IDX_8K
 #define HV_PGSZ_MASK_BASE	HV_PGSZ_MASK_8K
 
@@ -314,7 +341,7 @@ void tsb_grow(struct mm_struct *mm, unsi
 retry_tsb_alloc:
 	gfp_flags = GFP_KERNEL;
 	if (new_size > (PAGE_SIZE * 2))
-		gfp_flags = __GFP_NOWARN | __GFP_NORETRY;
+		gfp_flags |= __GFP_NOWARN | __GFP_NORETRY;
 
 	new_tsb = kmem_cache_alloc_node(tsb_caches[new_cache_index],
 					gfp_flags, numa_node_id());
diff -druNp linux-libre-3.8-gnu1/arch/sparc/mm/ultra.S linux-libre-3.8.13-gnu1/arch/sparc/mm/ultra.S
--- linux-libre-3.8-gnu1/arch/sparc/mm/ultra.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/sparc/mm/ultra.S	2013-05-11 16:57:46.000000000 -0400
@@ -53,6 +53,33 @@ __flush_tlb_mm:		/* 18 insns */
 	nop
 
 	.align		32
+	.globl		__flush_tlb_page
+__flush_tlb_page:	/* 22 insns */
+	/* %o0 = context, %o1 = vaddr */
+	rdpr		%pstate, %g7
+	andn		%g7, PSTATE_IE, %g2
+	wrpr		%g2, %pstate
+	mov		SECONDARY_CONTEXT, %o4
+	ldxa		[%o4] ASI_DMMU, %g2
+	stxa		%o0, [%o4] ASI_DMMU
+	andcc		%o1, 1, %g0
+	andn		%o1, 1, %o3
+	be,pn		%icc, 1f
+	 or		%o3, 0x10, %o3
+	stxa		%g0, [%o3] ASI_IMMU_DEMAP
+1:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
+	membar		#Sync
+	stxa		%g2, [%o4] ASI_DMMU
+	sethi		%hi(KERNBASE), %o4
+	flush		%o4
+	retl
+	 wrpr		%g7, 0x0, %pstate
+	nop
+	nop
+	nop
+	nop
+
+	.align		32
 	.globl		__flush_tlb_pending
 __flush_tlb_pending:	/* 26 insns */
 	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
@@ -203,6 +230,31 @@ __cheetah_flush_tlb_mm: /* 19 insns */
 	retl
 	 wrpr		%g7, 0x0, %pstate
 
+__cheetah_flush_tlb_page:	/* 22 insns */
+	/* %o0 = context, %o1 = vaddr */
+	rdpr		%pstate, %g7
+	andn		%g7, PSTATE_IE, %g2
+	wrpr		%g2, 0x0, %pstate
+	wrpr		%g0, 1, %tl
+	mov		PRIMARY_CONTEXT, %o4
+	ldxa		[%o4] ASI_DMMU, %g2
+	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %o3
+	sllx		%o3, CTX_PGSZ1_NUC_SHIFT, %o3
+	or		%o0, %o3, %o0	/* Preserve nucleus page size fields */
+	stxa		%o0, [%o4] ASI_DMMU
+	andcc		%o1, 1, %g0
+	be,pn		%icc, 1f
+	 andn		%o1, 1, %o3
+	stxa		%g0, [%o3] ASI_IMMU_DEMAP
+1:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
+	membar		#Sync
+	stxa		%g2, [%o4] ASI_DMMU
+	sethi		%hi(KERNBASE), %o4
+	flush		%o4
+	wrpr		%g0, 0, %tl
+	retl
+	 wrpr		%g7, 0x0, %pstate
+
 __cheetah_flush_tlb_pending:	/* 27 insns */
 	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
 	rdpr		%pstate, %g7
@@ -269,6 +321,20 @@ __hypervisor_flush_tlb_mm: /* 10 insns *
 	retl
 	 nop
 
+__hypervisor_flush_tlb_page: /* 11 insns */
+	/* %o0 = context, %o1 = vaddr */
+	mov		%o0, %g2
+	mov		%o1, %o0              /* ARG0: vaddr + IMMU-bit */
+	mov		%g2, %o1	      /* ARG1: mmu context */
+	mov		HV_MMU_ALL, %o2	      /* ARG2: flags */
+	srlx		%o0, PAGE_SHIFT, %o0
+	sllx		%o0, PAGE_SHIFT, %o0
+	ta		HV_MMU_UNMAP_ADDR_TRAP
+	brnz,pn		%o0, __hypervisor_tlb_tl0_error
+	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
+	retl
+	 nop
+
 __hypervisor_flush_tlb_pending: /* 16 insns */
 	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
 	sllx		%o1, 3, %g1
@@ -339,6 +405,13 @@ cheetah_patch_cachetlbops:
 	call		tlb_patch_one
 	 mov		19, %o2
 
+	sethi		%hi(__flush_tlb_page), %o0
+	or		%o0, %lo(__flush_tlb_page), %o0
+	sethi		%hi(__cheetah_flush_tlb_page), %o1
+	or		%o1, %lo(__cheetah_flush_tlb_page), %o1
+	call		tlb_patch_one
+	 mov		22, %o2
+
 	sethi		%hi(__flush_tlb_pending), %o0
 	or		%o0, %lo(__flush_tlb_pending), %o0
 	sethi		%hi(__cheetah_flush_tlb_pending), %o1
@@ -397,10 +470,9 @@ xcall_flush_tlb_mm:	/* 21 insns */
 	nop
 	nop
 
-	.globl		xcall_flush_tlb_pending
-xcall_flush_tlb_pending:	/* 21 insns */
-	/* %g5=context, %g1=nr, %g7=vaddrs[] */
-	sllx		%g1, 3, %g1
+	.globl		xcall_flush_tlb_page
+xcall_flush_tlb_page:	/* 17 insns */
+	/* %g5=context, %g1=vaddr */
 	mov		PRIMARY_CONTEXT, %g4
 	ldxa		[%g4] ASI_DMMU, %g2
 	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %g4
@@ -408,20 +480,16 @@ xcall_flush_tlb_pending:	/* 21 insns */
 	or		%g5, %g4, %g5
 	mov		PRIMARY_CONTEXT, %g4
 	stxa		%g5, [%g4] ASI_DMMU
-1:	sub		%g1, (1 << 3), %g1
-	ldx		[%g7 + %g1], %g5
-	andcc		%g5, 0x1, %g0
+	andcc		%g1, 0x1, %g0
 	be,pn		%icc, 2f
-
-	 andn		%g5, 0x1, %g5
+	 andn		%g1, 0x1, %g5
 	stxa		%g0, [%g5] ASI_IMMU_DEMAP
 2:	stxa		%g0, [%g5] ASI_DMMU_DEMAP
 	membar		#Sync
-	brnz,pt		%g1, 1b
-	 nop
 	stxa		%g2, [%g4] ASI_DMMU
 	retry
 	nop
+	nop
 
 	.globl		xcall_flush_tlb_kernel_range
 xcall_flush_tlb_kernel_range:	/* 25 insns */
@@ -656,15 +724,13 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 i
 	membar		#Sync
 	retry
 
-	.globl		__hypervisor_xcall_flush_tlb_pending
-__hypervisor_xcall_flush_tlb_pending: /* 21 insns */
-	/* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4,g6=scratch */
-	sllx		%g1, 3, %g1
+	.globl		__hypervisor_xcall_flush_tlb_page
+__hypervisor_xcall_flush_tlb_page: /* 17 insns */
+	/* %g5=ctx, %g1=vaddr */
 	mov		%o0, %g2
 	mov		%o1, %g3
 	mov		%o2, %g4
-1:	sub		%g1, (1 << 3), %g1
-	ldx		[%g7 + %g1], %o0	/* ARG0: virtual address */
+	mov		%g1, %o0	        /* ARG0: virtual address */
 	mov		%g5, %o1		/* ARG1: mmu context */
 	mov		HV_MMU_ALL, %o2		/* ARG2: flags */
 	srlx		%o0, PAGE_SHIFT, %o0
@@ -673,8 +739,6 @@ __hypervisor_xcall_flush_tlb_pending: /*
 	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
 	brnz,a,pn	%o0, __hypervisor_tlb_xcall_error
 	 mov		%o0, %g5
-	brnz,pt		%g1, 1b
-	 nop
 	mov		%g2, %o0
 	mov		%g3, %o1
 	mov		%g4, %o2
@@ -757,6 +821,13 @@ hypervisor_patch_cachetlbops:
 	call		tlb_patch_one
 	 mov		10, %o2
 
+	sethi		%hi(__flush_tlb_page), %o0
+	or		%o0, %lo(__flush_tlb_page), %o0
+	sethi		%hi(__hypervisor_flush_tlb_page), %o1
+	or		%o1, %lo(__hypervisor_flush_tlb_page), %o1
+	call		tlb_patch_one
+	 mov		11, %o2
+
 	sethi		%hi(__flush_tlb_pending), %o0
 	or		%o0, %lo(__flush_tlb_pending), %o0
 	sethi		%hi(__hypervisor_flush_tlb_pending), %o1
@@ -788,12 +859,12 @@ hypervisor_patch_cachetlbops:
 	call		tlb_patch_one
 	 mov		21, %o2
 
-	sethi		%hi(xcall_flush_tlb_pending), %o0
-	or		%o0, %lo(xcall_flush_tlb_pending), %o0
-	sethi		%hi(__hypervisor_xcall_flush_tlb_pending), %o1
-	or		%o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1
+	sethi		%hi(xcall_flush_tlb_page), %o0
+	or		%o0, %lo(xcall_flush_tlb_page), %o0
+	sethi		%hi(__hypervisor_xcall_flush_tlb_page), %o1
+	or		%o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
 	call		tlb_patch_one
-	 mov		21, %o2
+	 mov		17, %o2
 
 	sethi		%hi(xcall_flush_tlb_kernel_range), %o0
 	or		%o0, %lo(xcall_flush_tlb_kernel_range), %o0
diff -druNp linux-libre-3.8-gnu1/arch/tile/include/asm/compat.h linux-libre-3.8.13-gnu1/arch/tile/include/asm/compat.h
--- linux-libre-3.8-gnu1/arch/tile/include/asm/compat.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/tile/include/asm/compat.h	2013-05-11 16:57:46.000000000 -0400
@@ -296,6 +296,9 @@ long compat_sys_sync_file_range2(int fd,
 long compat_sys_fallocate(int fd, int mode,
 			  u32 offset_lo, u32 offset_hi,
 			  u32 len_lo, u32 len_hi);
+long compat_sys_llseek(unsigned int fd, unsigned int offset_high,
+		       unsigned int offset_low, loff_t __user * result,
+		       unsigned int origin);
 
 /* Assembly trampoline to avoid clobbering r0. */
 long _compat_sys_rt_sigreturn(void);
diff -druNp linux-libre-3.8-gnu1/arch/tile/kernel/compat.c linux-libre-3.8.13-gnu1/arch/tile/kernel/compat.c
--- linux-libre-3.8-gnu1/arch/tile/kernel/compat.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/tile/kernel/compat.c	2013-05-11 16:57:46.000000000 -0400
@@ -76,6 +76,18 @@ long compat_sys_fallocate(int fd, int mo
 			     ((loff_t)len_hi << 32) | len_lo);
 }
 
+/*
+ * Avoid bug in generic sys_llseek() that specifies offset_high and
+ * offset_low as "unsigned long", thus making it possible to pass
+ * a sign-extended high 32 bits in offset_low.
+ */
+long compat_sys_llseek(unsigned int fd, unsigned int offset_high,
+		       unsigned int offset_low, loff_t __user * result,
+		       unsigned int origin)
+{
+	return sys_llseek(fd, offset_high, offset_low, result, origin);
+}
+
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
@@ -83,6 +95,7 @@ long compat_sys_fallocate(int fd, int mo
 /* See comments in sys.c */
 #define compat_sys_fadvise64_64 sys32_fadvise64_64
 #define compat_sys_readahead sys32_readahead
+#define sys_llseek compat_sys_llseek
 
 /* Call the assembly trampolines where necessary. */
 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
diff -druNp linux-libre-3.8-gnu1/arch/tile/kernel/setup.c linux-libre-3.8.13-gnu1/arch/tile/kernel/setup.c
--- linux-libre-3.8-gnu1/arch/tile/kernel/setup.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/tile/kernel/setup.c	2013-05-11 16:57:46.000000000 -0400
@@ -1004,15 +1004,8 @@ void __cpuinit setup_cpu(int boot)
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
-/*
- * Note that the kernel can potentially support other compression
- * techniques than gz, though we don't do so by default.  If we ever
- * decide to do so we can either look for other filename extensions,
- * or just allow a file with this name to be compressed with an
- * arbitrary compressor (somewhat counterintuitively).
- */
 static int __initdata set_initramfs_file;
-static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
+static char __initdata initramfs_file[128] = "initramfs";
 
 static int __init setup_initramfs_file(char *str)
 {
@@ -1026,9 +1019,9 @@ static int __init setup_initramfs_file(c
 early_param("initramfs_file", setup_initramfs_file);
 
 /*
- * We look for an "initramfs.cpio.gz" file in the hvfs.
- * If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs.
+ * We look for a file called "initramfs" in the hvfs.  If there is one, we
+ * allocate some memory for it and it will be unpacked to the initramfs.
+ * If it's compressed, the initd code will uncompress it first.
  */
 static void __init load_hv_initrd(void)
 {
@@ -1038,10 +1031,16 @@ static void __init load_hv_initrd(void)
 
 	fd = hv_fs_findfile((HV_VirtAddr) initramfs_file);
 	if (fd == HV_ENOENT) {
-		if (set_initramfs_file)
+		if (set_initramfs_file) {
 			pr_warning("No such hvfs initramfs file '%s'\n",
 				   initramfs_file);
-		return;
+			return;
+		} else {
+			/* Try old backwards-compatible name. */
+			fd = hv_fs_findfile((HV_VirtAddr)"initramfs.cpio.gz");
+			if (fd == HV_ENOENT)
+				return;
+		}
 	}
 	BUG_ON(fd < 0);
 	stat = hv_fs_fstat(fd);
diff -druNp linux-libre-3.8-gnu1/arch/x86/boot/compressed/eboot.c linux-libre-3.8.13-gnu1/arch/x86/boot/compressed/eboot.c
--- linux-libre-3.8-gnu1/arch/x86/boot/compressed/eboot.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/boot/compressed/eboot.c	2013-05-11 16:57:46.000000000 -0400
@@ -19,23 +19,28 @@
 
 static efi_system_table_t *sys_table;
 
+static void efi_char16_printk(efi_char16_t *str)
+{
+	struct efi_simple_text_output_protocol *out;
+
+	out = (struct efi_simple_text_output_protocol *)sys_table->con_out;
+	efi_call_phys2(out->output_string, out, str);
+}
+
 static void efi_printk(char *str)
 {
 	char *s8;
 
 	for (s8 = str; *s8; s8++) {
-		struct efi_simple_text_output_protocol *out;
 		efi_char16_t ch[2] = { 0 };
 
 		ch[0] = *s8;
-		out = (struct efi_simple_text_output_protocol *)sys_table->con_out;
-
 		if (*s8 == '\n') {
 			efi_char16_t nl[2] = { '\r', 0 };
-			efi_call_phys2(out->output_string, out, nl);
+			efi_char16_printk(nl);
 		}
 
-		efi_call_phys2(out->output_string, out, ch);
+		efi_char16_printk(ch);
 	}
 }
 
@@ -709,7 +714,12 @@ static efi_status_t handle_ramdisks(efi_
 			if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16))
 				break;
 
-			*p++ = *str++;
+			if (*str == '/') {
+				*p++ = '\\';
+				*str++;
+			} else {
+				*p++ = *str++;
+			}
 		}
 
 		*p = '\0';
@@ -737,7 +747,9 @@ static efi_status_t handle_ramdisks(efi_
 		status = efi_call_phys5(fh->open, fh, &h, filename_16,
 					EFI_FILE_MODE_READ, (u64)0);
 		if (status != EFI_SUCCESS) {
-			efi_printk("Failed to open initrd file\n");
+			efi_printk("Failed to open initrd file: ");
+			efi_char16_printk(filename_16);
+			efi_printk("\n");
 			goto close_handles;
 		}
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/boot/compressed/Makefile linux-libre-3.8.13-gnu1/arch/x86/boot/compressed/Makefile
--- linux-libre-3.8-gnu1/arch/x86/boot/compressed/Makefile	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/boot/compressed/Makefile	2013-05-11 16:57:46.000000000 -0400
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
+targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -29,7 +29,6 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)
 	$(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
@@ -43,7 +42,7 @@ OBJCOPYFLAGS_vmlinux.bin :=  -R .comment
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
 
-targets += vmlinux.bin.all vmlinux.relocs
+targets += $(patsubst $(obj)/%,%,$(VMLINUX_OBJS)) vmlinux.bin.all vmlinux.relocs
 
 CMD_RELOCS = arch/x86/tools/relocs
 quiet_cmd_relocs = RELOCS  $@
diff -druNp linux-libre-3.8-gnu1/arch/x86/crypto/crc32c-pcl-intel-asm_64.S linux-libre-3.8.13-gnu1/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
--- linux-libre-3.8-gnu1/arch/x86/crypto/crc32c-pcl-intel-asm_64.S	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/crypto/crc32c-pcl-intel-asm_64.S	2013-05-11 16:57:46.000000000 -0400
@@ -42,6 +42,8 @@
  * SOFTWARE.
  */
 
+#include <asm/inst.h>
+
 ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
 
 .macro LABEL prefix n
@@ -224,10 +226,10 @@ LABEL crc_ %i
 	movdqa  (bufp), %xmm0			# 2 consts: K1:K2
 
 	movq    crc_init, %xmm1			# CRC for block 1
-	pclmulqdq $0x00,%xmm0,%xmm1		# Multiply by K2
+	PCLMULQDQ 0x00,%xmm0,%xmm1		# Multiply by K2
 
 	movq    crc1, %xmm2			# CRC for block 2
-	pclmulqdq $0x10, %xmm0, %xmm2		# Multiply by K1
+	PCLMULQDQ 0x10, %xmm0, %xmm2		# Multiply by K1
 
 	pxor    %xmm2,%xmm1
 	movq    %xmm1, %rax
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/kvm_host.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/kvm_host.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/kvm_host.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/kvm_host.h	2013-05-11 16:57:46.000000000 -0400
@@ -419,8 +419,8 @@ struct kvm_vcpu_arch {
 	gpa_t time;
 	struct pvclock_vcpu_time_info hv_clock;
 	unsigned int hw_tsc_khz;
-	unsigned int time_offset;
-	struct page *time_page;
+	struct gfn_to_hva_cache pv_time;
+	bool pv_time_enabled;
 	/* set guest stopped flag in pvclock flags field */
 	bool pvclock_set_guest_stopped_request;
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/mmzone_32.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/mmzone_32.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/mmzone_32.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/mmzone_32.h	2013-05-11 16:57:46.000000000 -0400
@@ -14,12 +14,6 @@ extern struct pglist_data *node_data[];
 
 #include <asm/numaq.h>
 
-extern void resume_map_numa_kva(pgd_t *pgd);
-
-#else /* !CONFIG_NUMA */
-
-static inline void resume_map_numa_kva(pgd_t *pgd) {}
-
 #endif /* CONFIG_NUMA */
 
 #ifdef CONFIG_DISCONTIGMEM
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/paravirt.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/paravirt.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/paravirt.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/paravirt.h	2013-05-11 16:57:46.000000000 -0400
@@ -703,7 +703,10 @@ static inline void arch_leave_lazy_mmu_m
 	PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave);
 }
 
-void arch_flush_lazy_mmu_mode(void);
+static inline void arch_flush_lazy_mmu_mode(void)
+{
+	PVOP_VCALL0(pv_mmu_ops.lazy_mode.flush);
+}
 
 static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
 				phys_addr_t phys, pgprot_t flags)
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/paravirt_types.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/paravirt_types.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/paravirt_types.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/paravirt_types.h	2013-05-11 16:57:46.000000000 -0400
@@ -91,6 +91,7 @@ struct pv_lazy_ops {
 	/* Set deferred update mode, used for batching operations. */
 	void (*enter)(void);
 	void (*leave)(void);
+	void (*flush)(void);
 };
 
 struct pv_time_ops {
@@ -679,6 +680,7 @@ void paravirt_end_context_switch(struct
 
 void paravirt_enter_lazy_mmu(void);
 void paravirt_leave_lazy_mmu(void);
+void paravirt_flush_lazy_mmu(void);
 
 void _paravirt_nop(void);
 u32 _paravirt_ident_32(u32);
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -31,6 +31,9 @@ typedef sigset_t compat_sigset_t;
 #include <uapi/asm/signal.h>
 #ifndef __ASSEMBLY__
 extern void do_notify_resume(struct pt_regs *, void *, __u32);
+
+#define __ARCH_HAS_SA_RESTORER
+
 #ifdef __i386__
 struct old_sigaction {
 	__sighandler_t sa_handler;
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/syscall.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/syscall.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/syscall.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/syscall.h	2013-05-11 16:57:46.000000000 -0400
@@ -29,13 +29,13 @@ extern const unsigned long sys_call_tabl
  */
 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
-	return regs->orig_ax & __SYSCALL_MASK;
+	return regs->orig_ax;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
 				    struct pt_regs *regs)
 {
-	regs->ax = regs->orig_ax & __SYSCALL_MASK;
+	regs->ax = regs->orig_ax;
 }
 
 static inline long syscall_get_error(struct task_struct *task,
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/tlb.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/tlb.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/tlb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/tlb.h	2013-05-11 16:57:46.000000000 -0400
@@ -7,7 +7,7 @@
 
 #define tlb_flush(tlb)							\
 {									\
-	if (tlb->fullmm == 0)						\
+	if (!tlb->fullmm && !tlb->need_flush_all) 			\
 		flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, 0UL);	\
 	else								\
 		flush_tlb_mm_range(tlb->mm, 0UL, TLB_FLUSH_ALL, 0UL);	\
diff -druNp linux-libre-3.8-gnu1/arch/x86/include/asm/xen/hypercall.h linux-libre-3.8.13-gnu1/arch/x86/include/asm/xen/hypercall.h
--- linux-libre-3.8-gnu1/arch/x86/include/asm/xen/hypercall.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/include/asm/xen/hypercall.h	2013-05-11 16:57:46.000000000 -0400
@@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count
 	return _hypercall3(int, console_io, cmd, count, str);
 }
 
-extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
+extern int __must_check xen_physdev_op_compat(int, void *);
 
 static inline int
 HYPERVISOR_physdev_op(int cmd, void *arg)
 {
 	int rc = _hypercall2(int, physdev_op, cmd, arg);
 	if (unlikely(rc == -ENOSYS))
-		rc = HYPERVISOR_physdev_op_compat(cmd, arg);
+		rc = xen_physdev_op_compat(cmd, arg);
 	return rc;
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/Kconfig linux-libre-3.8.13-gnu1/arch/x86/Kconfig
--- linux-libre-3.8-gnu1/arch/x86/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -1253,10 +1253,6 @@ config NODES_SHIFT
 	  Specify the maximum number of NUMA Nodes available on the target
 	  system.  Increases memory reserved to accommodate various tables.
 
-config HAVE_ARCH_ALLOC_REMAP
-	def_bool y
-	depends on X86_32 && NUMA
-
 config ARCH_HAVE_MEMORY_PRESENT
 	def_bool y
 	depends on X86_32 && DISCONTIGMEM
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/apic/apic.c linux-libre-3.8.13-gnu1/arch/x86/kernel/apic/apic.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/apic/apic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/apic/apic.c	2013-05-11 16:57:46.000000000 -0400
@@ -131,7 +131,7 @@ static int __init parse_lapic(char *arg)
 {
 	if (config_enabled(CONFIG_X86_32) && !arg)
 		force_enable_local_apic = 1;
-	else if (!strncmp(arg, "notscdeadline", 13))
+	else if (arg && !strncmp(arg, "notscdeadline", 13))
 		setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/cpu/mshyperv.c linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/mshyperv.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/cpu/mshyperv.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/mshyperv.c	2013-05-11 16:57:46.000000000 -0400
@@ -68,7 +68,8 @@ static void __init ms_hyperv_init_platfo
 	printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
 	       ms_hyperv.features, ms_hyperv.hints);
 
-	clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
+	if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
+		clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel.c linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel.c	2013-05-11 16:57:46.000000000 -0400
@@ -128,8 +128,14 @@ static struct event_constraint intel_gen
 };
 
 static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
-	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
-	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0),
+	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1),
+	EVENT_EXTRA_END
+};
+
+static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
+	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
 	EVENT_EXTRA_END
 };
 
@@ -2072,7 +2078,10 @@ __init int intel_pmu_init(void)
 		x86_pmu.event_constraints = intel_snb_event_constraints;
 		x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
 		x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
-		x86_pmu.extra_regs = intel_snb_extra_regs;
+		if (boot_cpu_data.x86_model == 45)
+			x86_pmu.extra_regs = intel_snbep_extra_regs;
+		else
+			x86_pmu.extra_regs = intel_snb_extra_regs;
 		/* all extra regs are per-cpu when HT is on */
 		x86_pmu.er_flags |= ERF_HAS_RSP_1;
 		x86_pmu.er_flags |= ERF_NO_HT_SHARING;
@@ -2098,7 +2107,10 @@ __init int intel_pmu_init(void)
 		x86_pmu.event_constraints = intel_snb_event_constraints;
 		x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
 		x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
-		x86_pmu.extra_regs = intel_snb_extra_regs;
+		if (boot_cpu_data.x86_model == 62)
+			x86_pmu.extra_regs = intel_snbep_extra_regs;
+		else
+			x86_pmu.extra_regs = intel_snb_extra_regs;
 		/* all extra regs are per-cpu when HT is on */
 		x86_pmu.er_flags |= ERF_HAS_RSP_1;
 		x86_pmu.er_flags |= ERF_NO_HT_SHARING;
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel_ds.c	2013-05-11 16:57:46.000000000 -0400
@@ -729,3 +729,13 @@ void intel_ds_init(void)
 		}
 	}
 }
+
+void perf_restore_debug_store(void)
+{
+	struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+
+	if (!x86_pmu.bts && !x86_pmu.pebs)
+		return;
+
+	wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds);
+}
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel_lbr.c	2013-05-11 16:57:46.000000000 -0400
@@ -310,7 +310,7 @@ void intel_pmu_lbr_read(void)
  * - in case there is no HW filter
  * - in case the HW filter has errata or limitations
  */
-static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
+static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
 {
 	u64 br_type = event->attr.branch_sample_type;
 	int mask = 0;
@@ -318,8 +318,11 @@ static void intel_pmu_setup_sw_lbr_filte
 	if (br_type & PERF_SAMPLE_BRANCH_USER)
 		mask |= X86_BR_USER;
 
-	if (br_type & PERF_SAMPLE_BRANCH_KERNEL)
+	if (br_type & PERF_SAMPLE_BRANCH_KERNEL) {
+		if (perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN))
+			return -EACCES;
 		mask |= X86_BR_KERNEL;
+	}
 
 	/* we ignore BRANCH_HV here */
 
@@ -339,6 +342,8 @@ static void intel_pmu_setup_sw_lbr_filte
 	 * be used by fixup code for some CPU
 	 */
 	event->hw.branch_reg.reg = mask;
+
+	return 0;
 }
 
 /*
@@ -386,7 +391,9 @@ int intel_pmu_setup_lbr_filter(struct pe
 	/*
 	 * setup SW LBR filter
 	 */
-	intel_pmu_setup_sw_lbr_filter(event);
+	ret = intel_pmu_setup_sw_lbr_filter(event);
+	if (ret)
+		return ret;
 
 	/*
 	 * setup HW LBR filter, if any
@@ -442,8 +449,18 @@ static int branch_type(unsigned long fro
 			return X86_BR_NONE;
 
 		addr = buf;
-	} else
-		addr = (void *)from;
+	} else {
+		/*
+		 * The LBR logs any address in the IP, even if the IP just
+		 * faulted. This means userspace can control the from address.
+		 * Ensure we don't blindy read any address by validating it is
+		 * a known text address.
+		 */
+		if (kernel_text_address(from))
+			addr = (void *)from;
+		else
+			return X86_BR_NONE;
+	}
 
 	/*
 	 * decoder needs to know the ABI especially
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel_uncore.c linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel_uncore.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/cpu/perf_event_intel_uncore.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/cpu/perf_event_intel_uncore.c	2013-05-11 16:57:46.000000000 -0400
@@ -2428,7 +2428,7 @@ static void __init uncore_types_exit(str
 static int __init uncore_type_init(struct intel_uncore_type *type)
 {
 	struct intel_uncore_pmu *pmus;
-	struct attribute_group *events_group;
+	struct attribute_group *attr_group;
 	struct attribute **attrs;
 	int i, j;
 
@@ -2455,19 +2455,19 @@ static int __init uncore_type_init(struc
 		while (type->event_descs[i].attr.attr.name)
 			i++;
 
-		events_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
-					sizeof(*events_group), GFP_KERNEL);
-		if (!events_group)
+		attr_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
+					sizeof(*attr_group), GFP_KERNEL);
+		if (!attr_group)
 			goto fail;
 
-		attrs = (struct attribute **)(events_group + 1);
-		events_group->name = "events";
-		events_group->attrs = attrs;
+		attrs = (struct attribute **)(attr_group + 1);
+		attr_group->name = "events";
+		attr_group->attrs = attrs;
 
 		for (j = 0; j < i; j++)
 			attrs[j] = &type->event_descs[j].attr.attr;
 
-		type->events_group = events_group;
+		type->events_group = attr_group;
 	}
 
 	type->pmu_group = &uncore_pmu_attr_group;
@@ -2853,6 +2853,7 @@ static int __init uncore_cpu_init(void)
 		msr_uncores = nhm_msr_uncores;
 		break;
 	case 42: /* Sandy Bridge */
+	case 58: /* Ivy Bridge */
 		if (snb_uncore_cbox.num_boxes > max_cores)
 			snb_uncore_cbox.num_boxes = max_cores;
 		msr_uncores = snb_msr_uncores;
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/head.c linux-libre-3.8.13-gnu1/arch/x86/kernel/head.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/head.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/head.c	2013-05-11 16:57:46.000000000 -0400
@@ -5,8 +5,6 @@
 #include <asm/setup.h>
 #include <asm/bios_ebda.h>
 
-#define BIOS_LOWMEM_KILOBYTES 0x413
-
 /*
  * The BIOS places the EBDA/XBDA at the top of conventional
  * memory, and usually decreases the reported amount of
@@ -16,17 +14,30 @@
  * chipset: reserve a page before VGA to prevent PCI prefetch
  * into it (errata #56). Usually the page is reserved anyways,
  * unless you have no PS/2 mouse plugged in.
+ *
+ * This functions is deliberately very conservative.  Losing
+ * memory in the bottom megabyte is rarely a problem, as long
+ * as we have enough memory to install the trampoline.  Using
+ * memory that is in use by the BIOS or by some DMA device
+ * the BIOS didn't shut down *is* a big problem.
  */
+
+#define BIOS_LOWMEM_KILOBYTES	0x413
+#define LOWMEM_CAP		0x9f000U	/* Absolute maximum */
+#define INSANE_CUTOFF		0x20000U	/* Less than this = insane */
+
 void __init reserve_ebda_region(void)
 {
 	unsigned int lowmem, ebda_addr;
 
-	/* To determine the position of the EBDA and the */
-	/* end of conventional memory, we need to look at */
-	/* the BIOS data area. In a paravirtual environment */
-	/* that area is absent. We'll just have to assume */
-	/* that the paravirt case can handle memory setup */
-	/* correctly, without our help. */
+	/*
+	 * To determine the position of the EBDA and the
+	 * end of conventional memory, we need to look at
+	 * the BIOS data area. In a paravirtual environment
+	 * that area is absent. We'll just have to assume
+	 * that the paravirt case can handle memory setup
+	 * correctly, without our help.
+	 */
 	if (paravirt_enabled())
 		return;
 
@@ -37,19 +48,23 @@ void __init reserve_ebda_region(void)
 	/* start of EBDA area */
 	ebda_addr = get_bios_ebda();
 
-	/* Fixup: bios puts an EBDA in the top 64K segment */
-	/* of conventional memory, but does not adjust lowmem. */
-	if ((lowmem - ebda_addr) <= 0x10000)
-		lowmem = ebda_addr;
+	/*
+	 * Note: some old Dells seem to need 4k EBDA without
+	 * reporting so, so just consider the memory above 0x9f000
+	 * to be off limits (bugzilla 2990).
+	 */
 
-	/* Fixup: bios does not report an EBDA at all. */
-	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
-	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
-		lowmem = 0x9f000;
+	/* If the EBDA address is below 128K, assume it is bogus */
+	if (ebda_addr < INSANE_CUTOFF)
+		ebda_addr = LOWMEM_CAP;
 
-	/* Paranoia: should never happen, but... */
-	if ((lowmem == 0) || (lowmem >= 0x100000))
-		lowmem = 0x9f000;
+	/* If lowmem is less than 128K, assume it is bogus */
+	if (lowmem < INSANE_CUTOFF)
+		lowmem = LOWMEM_CAP;
+
+	/* Use the lower of the lowmem and EBDA markers as the cutoff */
+	lowmem = min(lowmem, ebda_addr);
+	lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */
 
 	/* reserve all memory between lowmem and the 1MB mark */
 	memblock_reserve(lowmem, 0x100000 - lowmem);
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/irq.c linux-libre-3.8.13-gnu1/arch/x86/kernel/irq.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/irq.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/irq.c	2013-05-11 16:57:46.000000000 -0400
@@ -165,10 +165,6 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
 u64 arch_irq_stat(void)
 {
 	u64 sum = atomic_read(&irq_err_count);
-
-#ifdef CONFIG_X86_IO_APIC
-	sum += atomic_read(&irq_mis_count);
-#endif
 	return sum;
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/kvmclock.c linux-libre-3.8.13-gnu1/arch/x86/kernel/kvmclock.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/kvmclock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/kvmclock.c	2013-05-11 16:57:46.000000000 -0400
@@ -218,6 +218,9 @@ static void kvm_shutdown(void)
 void __init kvmclock_init(void)
 {
 	unsigned long mem;
+	int size;
+
+	size = PAGE_ALIGN(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
 
 	if (!kvm_para_available())
 		return;
@@ -231,16 +234,14 @@ void __init kvmclock_init(void)
 	printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
 		msr_kvm_system_time, msr_kvm_wall_clock);
 
-	mem = memblock_alloc(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS,
-			     PAGE_SIZE);
+	mem = memblock_alloc(size, PAGE_SIZE);
 	if (!mem)
 		return;
 	hv_clock = __va(mem);
 
 	if (kvm_register_clock("boot clock")) {
 		hv_clock = NULL;
-		memblock_free(mem,
-			sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
+		memblock_free(mem, size);
 		return;
 	}
 	pv_time_ops.sched_clock = kvm_clock_read;
@@ -275,7 +276,7 @@ int __init kvm_setup_vsyscall_timeinfo(v
 	struct pvclock_vcpu_time_info *vcpu_time;
 	unsigned int size;
 
-	size = sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS;
+	size = PAGE_ALIGN(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
 
 	preempt_disable();
 	cpu = smp_processor_id();
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/paravirt.c linux-libre-3.8.13-gnu1/arch/x86/kernel/paravirt.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/paravirt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/paravirt.c	2013-05-11 16:57:46.000000000 -0400
@@ -263,6 +263,18 @@ void paravirt_leave_lazy_mmu(void)
 	leave_lazy(PARAVIRT_LAZY_MMU);
 }
 
+void paravirt_flush_lazy_mmu(void)
+{
+	preempt_disable();
+
+	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+		arch_leave_lazy_mmu_mode();
+		arch_enter_lazy_mmu_mode();
+	}
+
+	preempt_enable();
+}
+
 void paravirt_start_context_switch(struct task_struct *prev)
 {
 	BUG_ON(preemptible());
@@ -292,18 +304,6 @@ enum paravirt_lazy_mode paravirt_get_laz
 	return this_cpu_read(paravirt_lazy_mode);
 }
 
-void arch_flush_lazy_mmu_mode(void)
-{
-	preempt_disable();
-
-	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
-		arch_leave_lazy_mmu_mode();
-		arch_enter_lazy_mmu_mode();
-	}
-
-	preempt_enable();
-}
-
 struct pv_info pv_info = {
 	.name = "bare hardware",
 	.paravirt_enabled = 0,
@@ -475,6 +475,7 @@ struct pv_mmu_ops pv_mmu_ops = {
 	.lazy_mode = {
 		.enter = paravirt_nop,
 		.leave = paravirt_nop,
+		.flush = paravirt_nop,
 	},
 
 	.set_fixmap = native_set_fixmap,
diff -druNp linux-libre-3.8-gnu1/arch/x86/kernel/pvclock.c linux-libre-3.8.13-gnu1/arch/x86/kernel/pvclock.c
--- linux-libre-3.8-gnu1/arch/x86/kernel/pvclock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kernel/pvclock.c	2013-05-11 16:57:46.000000000 -0400
@@ -185,7 +185,7 @@ int __init pvclock_init_vsyscall(struct
 
 	for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) {
 		__set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx,
-			     __pa_symbol(i) + (idx*PAGE_SIZE),
+			     __pa(i) + (idx*PAGE_SIZE),
 			     PAGE_KERNEL_VVAR);
 	}
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/kvm/emulate.c linux-libre-3.8.13-gnu1/arch/x86/kvm/emulate.c
--- linux-libre-3.8-gnu1/arch/x86/kvm/emulate.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kvm/emulate.c	2013-05-11 16:57:46.000000000 -0400
@@ -4030,6 +4030,10 @@ static int decode_operand(struct x86_emu
 		break;
 	case OpMem8:
 		ctxt->memop.bytes = 1;
+		if (ctxt->memop.type == OP_REG) {
+			ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1);
+			fetch_register_operand(&ctxt->memop);
+		}
 		goto mem_common;
 	case OpMem16:
 		ctxt->memop.bytes = 2;
diff -druNp linux-libre-3.8-gnu1/arch/x86/kvm/lapic.c linux-libre-3.8.13-gnu1/arch/x86/kvm/lapic.c
--- linux-libre-3.8-gnu1/arch/x86/kvm/lapic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kvm/lapic.c	2013-05-11 16:57:46.000000000 -0400
@@ -1781,7 +1781,7 @@ int kvm_lapic_enable_pv_eoi(struct kvm_v
 	if (!pv_eoi_enabled(vcpu))
 		return 0;
 	return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data,
-					 addr);
+					 addr, sizeof(u8));
 }
 
 void kvm_lapic_init(void)
diff -druNp linux-libre-3.8-gnu1/arch/x86/kvm/x86.c linux-libre-3.8.13-gnu1/arch/x86/kvm/x86.c
--- linux-libre-3.8-gnu1/arch/x86/kvm/x86.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/kvm/x86.c	2013-05-11 16:57:46.000000000 -0400
@@ -1408,10 +1408,9 @@ static int kvm_guest_time_update(struct
 	unsigned long flags, this_tsc_khz;
 	struct kvm_vcpu_arch *vcpu = &v->arch;
 	struct kvm_arch *ka = &v->kvm->arch;
-	void *shared_kaddr;
 	s64 kernel_ns, max_kernel_ns;
 	u64 tsc_timestamp, host_tsc;
-	struct pvclock_vcpu_time_info *guest_hv_clock;
+	struct pvclock_vcpu_time_info guest_hv_clock;
 	u8 pvclock_flags;
 	bool use_master_clock;
 
@@ -1465,7 +1464,7 @@ static int kvm_guest_time_update(struct
 
 	local_irq_restore(flags);
 
-	if (!vcpu->time_page)
+	if (!vcpu->pv_time_enabled)
 		return 0;
 
 	/*
@@ -1527,12 +1526,12 @@ static int kvm_guest_time_update(struct
 	 */
 	vcpu->hv_clock.version += 2;
 
-	shared_kaddr = kmap_atomic(vcpu->time_page);
-
-	guest_hv_clock = shared_kaddr + vcpu->time_offset;
+	if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time,
+		&guest_hv_clock, sizeof(guest_hv_clock))))
+		return 0;
 
 	/* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
-	pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
+	pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);
 
 	if (vcpu->pvclock_set_guest_stopped_request) {
 		pvclock_flags |= PVCLOCK_GUEST_STOPPED;
@@ -1545,12 +1544,9 @@ static int kvm_guest_time_update(struct
 
 	vcpu->hv_clock.flags = pvclock_flags;
 
-	memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
-	       sizeof(vcpu->hv_clock));
-
-	kunmap_atomic(shared_kaddr);
-
-	mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
+	kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
+				&vcpu->hv_clock,
+				sizeof(vcpu->hv_clock));
 	return 0;
 }
 
@@ -1829,7 +1825,8 @@ static int kvm_pv_enable_async_pf(struct
 		return 0;
 	}
 
-	if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa))
+	if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
+					sizeof(u32)))
 		return 1;
 
 	vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
@@ -1839,10 +1836,7 @@ static int kvm_pv_enable_async_pf(struct
 
 static void kvmclock_reset(struct kvm_vcpu *vcpu)
 {
-	if (vcpu->arch.time_page) {
-		kvm_release_page_dirty(vcpu->arch.time_page);
-		vcpu->arch.time_page = NULL;
-	}
+	vcpu->arch.pv_time_enabled = false;
 }
 
 static void accumulate_steal_time(struct kvm_vcpu *vcpu)
@@ -1948,6 +1942,7 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		break;
 	case MSR_KVM_SYSTEM_TIME_NEW:
 	case MSR_KVM_SYSTEM_TIME: {
+		u64 gpa_offset;
 		kvmclock_reset(vcpu);
 
 		vcpu->arch.time = data;
@@ -1957,14 +1952,14 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		if (!(data & 1))
 			break;
 
-		/* ...but clean it before doing the actual write */
-		vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
-
-		vcpu->arch.time_page =
-				gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
+		gpa_offset = data & ~(PAGE_MASK | 1);
 
-		if (is_error_page(vcpu->arch.time_page))
-			vcpu->arch.time_page = NULL;
+		if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+		     &vcpu->arch.pv_time, data & ~1ULL,
+		     sizeof(struct pvclock_vcpu_time_info)))
+			vcpu->arch.pv_time_enabled = false;
+		else
+			vcpu->arch.pv_time_enabled = true;
 
 		break;
 	}
@@ -1981,7 +1976,8 @@ int kvm_set_msr_common(struct kvm_vcpu *
 			return 1;
 
 		if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
-							data & KVM_STEAL_VALID_BITS))
+						data & KVM_STEAL_VALID_BITS,
+						sizeof(struct kvm_steal_time)))
 			return 1;
 
 		vcpu->arch.st.msr_val = data;
@@ -2967,7 +2963,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(s
  */
 static int kvm_set_guest_paused(struct kvm_vcpu *vcpu)
 {
-	if (!vcpu->arch.time_page)
+	if (!vcpu->arch.pv_time_enabled)
 		return -EINVAL;
 	vcpu->arch.pvclock_set_guest_stopped_request = true;
 	kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -6661,6 +6657,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *
 		goto fail_free_wbinvd_dirty_mask;
 
 	vcpu->arch.ia32_tsc_adjust_msr = 0x0;
+	vcpu->arch.pv_time_enabled = false;
 	kvm_async_pf_hash_reset(vcpu);
 	kvm_pmu_init(vcpu);
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/lguest/boot.c linux-libre-3.8.13-gnu1/arch/x86/lguest/boot.c
--- linux-libre-3.8-gnu1/arch/x86/lguest/boot.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/lguest/boot.c	2013-05-11 16:57:46.000000000 -0400
@@ -1333,6 +1333,7 @@ __init void lguest_init(void)
 	pv_mmu_ops.read_cr3 = lguest_read_cr3;
 	pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu;
 	pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode;
+	pv_mmu_ops.lazy_mode.flush = paravirt_flush_lazy_mmu;
 	pv_mmu_ops.pte_update = lguest_pte_update;
 	pv_mmu_ops.pte_update_defer = lguest_pte_update;
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/lib/usercopy_64.c linux-libre-3.8.13-gnu1/arch/x86/lib/usercopy_64.c
--- linux-libre-3.8-gnu1/arch/x86/lib/usercopy_64.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/lib/usercopy_64.c	2013-05-11 16:57:46.000000000 -0400
@@ -74,10 +74,10 @@ copy_user_handle_tail(char *to, char *fr
 	char c;
 	unsigned zero_len;
 
-	for (; len; --len) {
+	for (; len; --len, to++) {
 		if (__get_user_nocheck(c, from++, sizeof(char)))
 			break;
-		if (__put_user_nocheck(c, to++, sizeof(char)))
+		if (__put_user_nocheck(c, to, sizeof(char)))
 			break;
 	}
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/mm/fault.c linux-libre-3.8.13-gnu1/arch/x86/mm/fault.c
--- linux-libre-3.8-gnu1/arch/x86/mm/fault.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/mm/fault.c	2013-05-11 16:57:46.000000000 -0400
@@ -378,10 +378,12 @@ static noinline __kprobes int vmalloc_fa
 	if (pgd_none(*pgd_ref))
 		return -1;
 
-	if (pgd_none(*pgd))
+	if (pgd_none(*pgd)) {
 		set_pgd(pgd, *pgd_ref);
-	else
+		arch_flush_lazy_mmu_mode();
+	} else {
 		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+	}
 
 	/*
 	 * Below here mismatches are bugs because these lower tables
diff -druNp linux-libre-3.8-gnu1/arch/x86/mm/init.c linux-libre-3.8.13-gnu1/arch/x86/mm/init.c
--- linux-libre-3.8-gnu1/arch/x86/mm/init.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/mm/init.c	2013-05-11 16:57:46.000000000 -0400
@@ -45,11 +45,15 @@ static void __init find_early_table_spac
 	int i;
 	unsigned long puds = 0, pmds = 0, ptes = 0, tables;
 	unsigned long start = 0, good_end;
+	unsigned long pgd_extra = 0;
 	phys_addr_t base;
 
 	for (i = 0; i < nr_range; i++) {
 		unsigned long range, extra;
 
+		if ((mr[i].end >> PGDIR_SHIFT) - (mr[i].start >> PGDIR_SHIFT))
+			pgd_extra++;
+
 		range = mr[i].end - mr[i].start;
 		puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
 
@@ -74,6 +78,7 @@ static void __init find_early_table_spac
 	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
 	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
 	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
+	tables += (pgd_extra * PAGE_SIZE);
 
 #ifdef CONFIG_X86_32
 	/* for fixmap */
diff -druNp linux-libre-3.8-gnu1/arch/x86/mm/numa_32.c linux-libre-3.8.13-gnu1/arch/x86/mm/numa_32.c
--- linux-libre-3.8-gnu1/arch/x86/mm/numa_32.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/mm/numa_32.c	2013-05-11 16:57:46.000000000 -0400
@@ -73,167 +73,6 @@ unsigned long node_memmap_size_bytes(int
 
 extern unsigned long highend_pfn, highstart_pfn;
 
-#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
-
-static void *node_remap_start_vaddr[MAX_NUMNODES];
-void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
-
-/*
- * Remap memory allocator
- */
-static unsigned long node_remap_start_pfn[MAX_NUMNODES];
-static void *node_remap_end_vaddr[MAX_NUMNODES];
-static void *node_remap_alloc_vaddr[MAX_NUMNODES];
-
-/**
- * alloc_remap - Allocate remapped memory
- * @nid: NUMA node to allocate memory from
- * @size: The size of allocation
- *
- * Allocate @size bytes from the remap area of NUMA node @nid.  The
- * size of the remap area is predetermined by init_alloc_remap() and
- * only the callers considered there should call this function.  For
- * more info, please read the comment on top of init_alloc_remap().
- *
- * The caller must be ready to handle allocation failure from this
- * function and fall back to regular memory allocator in such cases.
- *
- * CONTEXT:
- * Single CPU early boot context.
- *
- * RETURNS:
- * Pointer to the allocated memory on success, %NULL on failure.
- */
-void *alloc_remap(int nid, unsigned long size)
-{
-	void *allocation = node_remap_alloc_vaddr[nid];
-
-	size = ALIGN(size, L1_CACHE_BYTES);
-
-	if (!allocation || (allocation + size) > node_remap_end_vaddr[nid])
-		return NULL;
-
-	node_remap_alloc_vaddr[nid] += size;
-	memset(allocation, 0, size);
-
-	return allocation;
-}
-
-#ifdef CONFIG_HIBERNATION
-/**
- * resume_map_numa_kva - add KVA mapping to the temporary page tables created
- *                       during resume from hibernation
- * @pgd_base - temporary resume page directory
- */
-void resume_map_numa_kva(pgd_t *pgd_base)
-{
-	int node;
-
-	for_each_online_node(node) {
-		unsigned long start_va, start_pfn, nr_pages, pfn;
-
-		start_va = (unsigned long)node_remap_start_vaddr[node];
-		start_pfn = node_remap_start_pfn[node];
-		nr_pages = (node_remap_end_vaddr[node] -
-			    node_remap_start_vaddr[node]) >> PAGE_SHIFT;
-
-		printk(KERN_DEBUG "%s: node %d\n", __func__, node);
-
-		for (pfn = 0; pfn < nr_pages; pfn += PTRS_PER_PTE) {
-			unsigned long vaddr = start_va + (pfn << PAGE_SHIFT);
-			pgd_t *pgd = pgd_base + pgd_index(vaddr);
-			pud_t *pud = pud_offset(pgd, vaddr);
-			pmd_t *pmd = pmd_offset(pud, vaddr);
-
-			set_pmd(pmd, pfn_pmd(start_pfn + pfn,
-						PAGE_KERNEL_LARGE_EXEC));
-
-			printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n",
-				__func__, vaddr, start_pfn + pfn);
-		}
-	}
-}
-#endif
-
-/**
- * init_alloc_remap - Initialize remap allocator for a NUMA node
- * @nid: NUMA node to initizlie remap allocator for
- *
- * NUMA nodes may end up without any lowmem.  As allocating pgdat and
- * memmap on a different node with lowmem is inefficient, a special
- * remap allocator is implemented which can be used by alloc_remap().
- *
- * For each node, the amount of memory which will be necessary for
- * pgdat and memmap is calculated and two memory areas of the size are
- * allocated - one in the node and the other in lowmem; then, the area
- * in the node is remapped to the lowmem area.
- *
- * As pgdat and memmap must be allocated in lowmem anyway, this
- * doesn't waste lowmem address space; however, the actual lowmem
- * which gets remapped over is wasted.  The amount shouldn't be
- * problematic on machines this feature will be used.
- *
- * Initialization failure isn't fatal.  alloc_remap() is used
- * opportunistically and the callers will fall back to other memory
- * allocation mechanisms on failure.
- */
-void __init init_alloc_remap(int nid, u64 start, u64 end)
-{
-	unsigned long start_pfn = start >> PAGE_SHIFT;
-	unsigned long end_pfn = end >> PAGE_SHIFT;
-	unsigned long size, pfn;
-	u64 node_pa, remap_pa;
-	void *remap_va;
-
-	/*
-	 * The acpi/srat node info can show hot-add memroy zones where
-	 * memory could be added but not currently present.
-	 */
-	printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
-	       nid, start_pfn, end_pfn);
-
-	/* calculate the necessary space aligned to large page size */
-	size = node_memmap_size_bytes(nid, start_pfn, end_pfn);
-	size += ALIGN(sizeof(pg_data_t), PAGE_SIZE);
-	size = ALIGN(size, LARGE_PAGE_BYTES);
-
-	/* allocate node memory and the lowmem remap area */
-	node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES);
-	if (!node_pa) {
-		pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n",
-			   size, nid);
-		return;
-	}
-	memblock_reserve(node_pa, size);
-
-	remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT,
-					  max_low_pfn << PAGE_SHIFT,
-					  size, LARGE_PAGE_BYTES);
-	if (!remap_pa) {
-		pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n",
-			   size, nid);
-		memblock_free(node_pa, size);
-		return;
-	}
-	memblock_reserve(remap_pa, size);
-	remap_va = phys_to_virt(remap_pa);
-
-	/* perform actual remap */
-	for (pfn = 0; pfn < size >> PAGE_SHIFT; pfn += PTRS_PER_PTE)
-		set_pmd_pfn((unsigned long)remap_va + (pfn << PAGE_SHIFT),
-			    (node_pa >> PAGE_SHIFT) + pfn,
-			    PAGE_KERNEL_LARGE);
-
-	/* initialize remap allocator parameters */
-	node_remap_start_pfn[nid] = node_pa >> PAGE_SHIFT;
-	node_remap_start_vaddr[nid] = remap_va;
-	node_remap_end_vaddr[nid] = remap_va + size;
-	node_remap_alloc_vaddr[nid] = remap_va;
-
-	printk(KERN_DEBUG "remap_alloc: node %d [%08llx-%08llx) -> [%p-%p)\n",
-	       nid, node_pa, node_pa + size, remap_va, remap_va + size);
-}
-
 void __init initmem_init(void)
 {
 	x86_numa_init();
diff -druNp linux-libre-3.8-gnu1/arch/x86/mm/numa.c linux-libre-3.8.13-gnu1/arch/x86/mm/numa.c
--- linux-libre-3.8-gnu1/arch/x86/mm/numa.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/mm/numa.c	2013-05-11 16:57:46.000000000 -0400
@@ -193,7 +193,6 @@ int __init numa_add_memblk(int nid, u64
 static void __init setup_node_data(int nid, u64 start, u64 end)
 {
 	const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
-	bool remapped = false;
 	u64 nd_pa;
 	void *nd;
 	int tnid;
@@ -205,37 +204,28 @@ static void __init setup_node_data(int n
 	if (end && (end - start) < NODE_MIN_SIZE)
 		return;
 
-	/* initialize remap allocator before aligning to ZONE_ALIGN */
-	init_alloc_remap(nid, start, end);
-
 	start = roundup(start, ZONE_ALIGN);
 
 	printk(KERN_INFO "Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
 	       nid, start, end - 1);
 
 	/*
-	 * Allocate node data.  Try remap allocator first, node-local
-	 * memory and then any node.  Never allocate in DMA zone.
+	 * Allocate node data.  Try node-local memory and then any node.
+	 * Never allocate in DMA zone.
 	 */
-	nd = alloc_remap(nid, nd_size);
-	if (nd) {
-		nd_pa = __pa(nd);
-		remapped = true;
-	} else {
-		nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid);
-		if (!nd_pa) {
-			pr_err("Cannot find %zu bytes in node %d\n",
-			       nd_size, nid);
-			return;
-		}
-		nd = __va(nd_pa);
+	nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid);
+	if (!nd_pa) {
+		pr_err("Cannot find %zu bytes in node %d\n",
+		       nd_size, nid);
+		return;
 	}
+	nd = __va(nd_pa);
 
 	/* report and initialize */
-	printk(KERN_INFO "  NODE_DATA [mem %#010Lx-%#010Lx]%s\n",
-	       nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : "");
+	printk(KERN_INFO "  NODE_DATA [mem %#010Lx-%#010Lx]\n",
+	       nd_pa, nd_pa + nd_size - 1);
 	tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
-	if (!remapped && tnid != nid)
+	if (tnid != nid)
 		printk(KERN_INFO "    NODE_DATA(%d) on node %d\n", nid, tnid);
 
 	node_data[nid] = nd;
diff -druNp linux-libre-3.8-gnu1/arch/x86/mm/numa_internal.h linux-libre-3.8.13-gnu1/arch/x86/mm/numa_internal.h
--- linux-libre-3.8-gnu1/arch/x86/mm/numa_internal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/mm/numa_internal.h	2013-05-11 16:57:46.000000000 -0400
@@ -21,12 +21,6 @@ void __init numa_reset_distance(void);
 
 void __init x86_numa_init(void);
 
-#ifdef CONFIG_X86_64
-static inline void init_alloc_remap(int nid, u64 start, u64 end)	{ }
-#else
-void __init init_alloc_remap(int nid, u64 start, u64 end);
-#endif
-
 #ifdef CONFIG_NUMA_EMU
 void __init numa_emulation(struct numa_meminfo *numa_meminfo,
 			   int numa_dist_cnt);
diff -druNp linux-libre-3.8-gnu1/arch/x86/mm/pgtable.c linux-libre-3.8.13-gnu1/arch/x86/mm/pgtable.c
--- linux-libre-3.8-gnu1/arch/x86/mm/pgtable.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/mm/pgtable.c	2013-05-11 16:57:46.000000000 -0400
@@ -58,6 +58,13 @@ void ___pte_free_tlb(struct mmu_gather *
 void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
 	paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
+	/*
+	 * NOTE! For PAE, any changes to the top page-directory-pointer-table
+	 * entries need a full cr3 reload to flush.
+	 */
+#ifdef CONFIG_X86_PAE
+	tlb->need_flush_all = 1;
+#endif
 	tlb_remove_page(tlb, virt_to_page(pmd));
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/pci/xen.c linux-libre-3.8.13-gnu1/arch/x86/pci/xen.c
--- linux-libre-3.8-gnu1/arch/x86/pci/xen.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/pci/xen.c	2013-05-11 16:57:46.000000000 -0400
@@ -162,6 +162,9 @@ static int xen_setup_msi_irqs(struct pci
 	struct msi_desc *msidesc;
 	int *v;
 
+	if (type == PCI_CAP_ID_MSI && nvec > 1)
+		return 1;
+
 	v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
 	if (!v)
 		return -ENOMEM;
@@ -220,6 +223,9 @@ static int xen_hvm_setup_msi_irqs(struct
 	struct msi_desc *msidesc;
 	struct msi_msg msg;
 
+	if (type == PCI_CAP_ID_MSI && nvec > 1)
+		return 1;
+
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 		__read_msi_msg(msidesc, &msg);
 		pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
@@ -263,6 +269,9 @@ static int xen_initdom_setup_msi_irqs(st
 	int ret = 0;
 	struct msi_desc *msidesc;
 
+	if (type == PCI_CAP_ID_MSI && nvec > 1)
+		return 1;
+
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
 		struct physdev_map_pirq map_irq;
 		domid_t domid;
diff -druNp linux-libre-3.8-gnu1/arch/x86/platform/efi/efi.c linux-libre-3.8.13-gnu1/arch/x86/platform/efi/efi.c
--- linux-libre-3.8-gnu1/arch/x86/platform/efi/efi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/platform/efi/efi.c	2013-05-11 16:57:46.000000000 -0400
@@ -85,9 +85,10 @@ int efi_enabled(int facility)
 }
 EXPORT_SYMBOL(efi_enabled);
 
+static bool disable_runtime = false;
 static int __init setup_noefi(char *arg)
 {
-	clear_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
+	disable_runtime = true;
 	return 0;
 }
 early_param("noefi", setup_noefi);
@@ -734,7 +735,7 @@ void __init efi_init(void)
 	if (!efi_is_native())
 		pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
 	else {
-		if (efi_runtime_init())
+		if (disable_runtime || efi_runtime_init())
 			return;
 		set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
 	}
diff -druNp linux-libre-3.8-gnu1/arch/x86/power/cpu.c linux-libre-3.8.13-gnu1/arch/x86/power/cpu.c
--- linux-libre-3.8-gnu1/arch/x86/power/cpu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/power/cpu.c	2013-05-11 16:57:46.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/suspend.h>
 #include <linux/export.h>
 #include <linux/smp.h>
+#include <linux/perf_event.h>
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
@@ -228,6 +229,7 @@ static void __restore_processor_state(st
 	do_fpu_end();
 	x86_platform.restore_sched_clock_state();
 	mtrr_bp_restore();
+	perf_restore_debug_store();
 }
 
 /* Needed by apm.c */
diff -druNp linux-libre-3.8-gnu1/arch/x86/power/hibernate_32.c linux-libre-3.8.13-gnu1/arch/x86/power/hibernate_32.c
--- linux-libre-3.8-gnu1/arch/x86/power/hibernate_32.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/power/hibernate_32.c	2013-05-11 16:57:46.000000000 -0400
@@ -129,8 +129,6 @@ static int resume_physical_mapping_init(
 		}
 	}
 
-	resume_map_numa_kva(pgd_base);
-
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/xen/enlighten.c linux-libre-3.8.13-gnu1/arch/x86/xen/enlighten.c
--- linux-libre-3.8-gnu1/arch/x86/xen/enlighten.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/xen/enlighten.c	2013-05-11 16:57:46.000000000 -0400
@@ -67,6 +67,7 @@
 #include <asm/hypervisor.h>
 #include <asm/mwait.h>
 #include <asm/pci_x86.h>
+#include <asm/pat.h>
 
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
@@ -1417,7 +1418,14 @@ asmlinkage void __init xen_start_kernel(
 	 */
 	acpi_numa = -1;
 #endif
-
+#ifdef CONFIG_X86_PAT
+	/*
+	 * For right now disable the PAT. We should remove this once
+	 * git commit 8eaffa67b43e99ae581622c5133e20b0f48bcef1
+	 * (xen/pat: Disable PAT support for now) is reverted.
+	 */
+	pat_enabled = 0;
+#endif
 	/* Don't do the full vcpu_info placement stuff until we have a
 	   possible map and a non-dummy shared_info. */
 	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
@@ -1581,8 +1589,11 @@ static int __cpuinit xen_hvm_cpu_notify(
 	switch (action) {
 	case CPU_UP_PREPARE:
 		xen_vcpu_setup(cpu);
-		if (xen_have_vector_callback)
+		if (xen_have_vector_callback) {
 			xen_init_lock_cpu(cpu);
+			if (xen_feature(XENFEAT_hvm_safe_pvclock))
+				xen_setup_timer(cpu);
+		}
 		break;
 	default:
 		break;
diff -druNp linux-libre-3.8-gnu1/arch/x86/xen/mmu.c linux-libre-3.8.13-gnu1/arch/x86/xen/mmu.c
--- linux-libre-3.8-gnu1/arch/x86/xen/mmu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/xen/mmu.c	2013-05-11 16:57:46.000000000 -0400
@@ -2190,6 +2190,7 @@ static const struct pv_mmu_ops xen_mmu_o
 	.lazy_mode = {
 		.enter = paravirt_enter_lazy_mmu,
 		.leave = xen_leave_lazy_mmu,
+		.flush = paravirt_flush_lazy_mmu,
 	},
 
 	.set_fixmap = xen_set_fixmap,
diff -druNp linux-libre-3.8-gnu1/arch/x86/xen/smp.c linux-libre-3.8.13-gnu1/arch/x86/xen/smp.c
--- linux-libre-3.8-gnu1/arch/x86/xen/smp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/xen/smp.c	2013-05-11 16:57:46.000000000 -0400
@@ -658,6 +658,8 @@ static void xen_hvm_cpu_die(unsigned int
 	unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
 	unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
 	unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+	xen_uninit_lock_cpu(cpu);
+	xen_teardown_timer(cpu);
 	native_cpu_die(cpu);
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/x86/xen/spinlock.c linux-libre-3.8.13-gnu1/arch/x86/xen/spinlock.c
--- linux-libre-3.8-gnu1/arch/x86/xen/spinlock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/xen/spinlock.c	2013-05-11 16:57:46.000000000 -0400
@@ -328,7 +328,6 @@ static noinline void xen_spin_unlock_slo
 		if (per_cpu(lock_spinners, cpu) == xl) {
 			ADD_STATS(released_slow_kicked, 1);
 			xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR);
-			break;
 		}
 	}
 }
diff -druNp linux-libre-3.8-gnu1/arch/x86/xen/time.c linux-libre-3.8.13-gnu1/arch/x86/xen/time.c
--- linux-libre-3.8-gnu1/arch/x86/xen/time.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/x86/xen/time.c	2013-05-11 16:57:46.000000000 -0400
@@ -497,7 +497,11 @@ static void xen_hvm_setup_cpu_clockevent
 {
 	int cpu = smp_processor_id();
 	xen_setup_runstate_info(cpu);
-	xen_setup_timer(cpu);
+	/*
+	 * xen_setup_timer(cpu) - snprintf is bad in atomic context. Hence
+	 * doing it xen_hvm_cpu_notify (which gets called by smp_init during
+	 * early bootup and also during CPU hotplug events).
+	 */
 	xen_setup_cpu_clockevents();
 }
 
diff -druNp linux-libre-3.8-gnu1/arch/xtensa/include/asm/signal.h linux-libre-3.8.13-gnu1/arch/xtensa/include/asm/signal.h
--- linux-libre-3.8-gnu1/arch/xtensa/include/asm/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/arch/xtensa/include/asm/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -21,6 +21,7 @@ struct sigaction {
 	void (*sa_restorer)(void);
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
+#define __ARCH_HAS_SA_RESTORER
 
 struct k_sigaction {
 	struct sigaction sa;
diff -druNp linux-libre-3.8-gnu1/block/blk-sysfs.c linux-libre-3.8.13-gnu1/block/blk-sysfs.c
--- linux-libre-3.8-gnu1/block/blk-sysfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/block/blk-sysfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -229,6 +229,8 @@ queue_store_##name(struct request_queue
 	unsigned long val;						\
 	ssize_t ret;							\
 	ret = queue_var_store(&val, page, count);			\
+	if (ret < 0)							\
+		 return ret;						\
 	if (neg)							\
 		val = !val;						\
 									\
diff -druNp linux-libre-3.8-gnu1/block/genhd.c linux-libre-3.8.13-gnu1/block/genhd.c
--- linux-libre-3.8-gnu1/block/genhd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/block/genhd.c	2013-05-11 16:57:46.000000000 -0400
@@ -25,7 +25,7 @@ static DEFINE_MUTEX(block_class_lock);
 struct kobject *block_depr;
 
 /* for extended dynamic devt allocation, currently only one major is used */
-#define MAX_EXT_DEVT		(1 << MINORBITS)
+#define NR_EXT_DEVT		(1 << MINORBITS)
 
 /* For extended devt allocation.  ext_devt_mutex prevents look up
  * results from going away underneath its user.
@@ -422,17 +422,18 @@ int blk_alloc_devt(struct hd_struct *par
 	do {
 		if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL))
 			return -ENOMEM;
+		mutex_lock(&ext_devt_mutex);
 		rc = idr_get_new(&ext_devt_idr, part, &idx);
+		if (!rc && idx >= NR_EXT_DEVT) {
+			idr_remove(&ext_devt_idr, idx);
+			rc = -EBUSY;
+		}
+		mutex_unlock(&ext_devt_mutex);
 	} while (rc == -EAGAIN);
 
 	if (rc)
 		return rc;
 
-	if (idx > MAX_EXT_DEVT) {
-		idr_remove(&ext_devt_idr, idx);
-		return -EBUSY;
-	}
-
 	*devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx));
 	return 0;
 }
@@ -646,7 +647,6 @@ void del_gendisk(struct gendisk *disk)
 	disk_part_iter_exit(&piter);
 
 	invalidate_partition(disk, 0);
-	blk_free_devt(disk_to_dev(disk)->devt);
 	set_capacity(disk, 0);
 	disk->flags &= ~GENHD_FL_UP;
 
@@ -664,6 +664,7 @@ void del_gendisk(struct gendisk *disk)
 	if (!sysfs_deprecated)
 		sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 	device_del(disk_to_dev(disk));
+	blk_free_devt(disk_to_dev(disk)->devt);
 }
 EXPORT_SYMBOL(del_gendisk);
 
diff -druNp linux-libre-3.8-gnu1/block/partition-generic.c linux-libre-3.8.13-gnu1/block/partition-generic.c
--- linux-libre-3.8-gnu1/block/partition-generic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/block/partition-generic.c	2013-05-11 16:57:46.000000000 -0400
@@ -249,11 +249,11 @@ void delete_partition(struct gendisk *di
 	if (!part)
 		return;
 
-	blk_free_devt(part_devt(part));
 	rcu_assign_pointer(ptbl->part[partno], NULL);
 	rcu_assign_pointer(ptbl->last_lookup, NULL);
 	kobject_put(part->holder_dir);
 	device_del(part_to_dev(part));
+	blk_free_devt(part_devt(part));
 
 	hd_struct_put(part);
 }
diff -druNp linux-libre-3.8-gnu1/crypto/ablkcipher.c linux-libre-3.8.13-gnu1/crypto/ablkcipher.c
--- linux-libre-3.8-gnu1/crypto/ablkcipher.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/ablkcipher.c	2013-05-11 16:57:46.000000000 -0400
@@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(stru
 {
 	struct crypto_report_blkcipher rblkcipher;
 
-	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
-	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
-		 alg->cra_ablkcipher.geniv ?: "<default>");
+	strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type));
+	strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<default>",
+		sizeof(rblkcipher.geniv));
 
 	rblkcipher.blocksize = alg->cra_blocksize;
 	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
@@ -469,9 +469,9 @@ static int crypto_givcipher_report(struc
 {
 	struct crypto_report_blkcipher rblkcipher;
 
-	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
-	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
-		 alg->cra_ablkcipher.geniv ?: "<built-in>");
+	strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type));
+	strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<built-in>",
+		sizeof(rblkcipher.geniv));
 
 	rblkcipher.blocksize = alg->cra_blocksize;
 	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
diff -druNp linux-libre-3.8-gnu1/crypto/aead.c linux-libre-3.8.13-gnu1/crypto/aead.c
--- linux-libre-3.8-gnu1/crypto/aead.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/aead.c	2013-05-11 16:57:46.000000000 -0400
@@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_
 	struct crypto_report_aead raead;
 	struct aead_alg *aead = &alg->cra_aead;
 
-	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
-	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
-		 aead->geniv ?: "<built-in>");
+	strncpy(raead.type, "aead", sizeof(raead.type));
+	strncpy(raead.geniv, aead->geniv ?: "<built-in>", sizeof(raead.geniv));
 
 	raead.blocksize = alg->cra_blocksize;
 	raead.maxauthsize = aead->maxauthsize;
@@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct
 	struct crypto_report_aead raead;
 	struct aead_alg *aead = &alg->cra_aead;
 
-	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
-	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
+	strncpy(raead.type, "nivaead", sizeof(raead.type));
+	strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv));
 
 	raead.blocksize = alg->cra_blocksize;
 	raead.maxauthsize = aead->maxauthsize;
diff -druNp linux-libre-3.8-gnu1/crypto/ahash.c linux-libre-3.8.13-gnu1/crypto/ahash.c
--- linux-libre-3.8-gnu1/crypto/ahash.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/ahash.c	2013-05-11 16:57:46.000000000 -0400
@@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk
 {
 	struct crypto_report_hash rhash;
 
-	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
+	strncpy(rhash.type, "ahash", sizeof(rhash.type));
 
 	rhash.blocksize = alg->cra_blocksize;
 	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
diff -druNp linux-libre-3.8-gnu1/crypto/algif_hash.c linux-libre-3.8.13-gnu1/crypto/algif_hash.c
--- linux-libre-3.8-gnu1/crypto/algif_hash.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/algif_hash.c	2013-05-11 16:57:46.000000000 -0400
@@ -161,6 +161,8 @@ static int hash_recvmsg(struct kiocb *un
 	else if (len < ds)
 		msg->msg_flags |= MSG_TRUNC;
 
+	msg->msg_namelen = 0;
+
 	lock_sock(sk);
 	if (ctx->more) {
 		ctx->more = 0;
diff -druNp linux-libre-3.8-gnu1/crypto/algif_skcipher.c linux-libre-3.8.13-gnu1/crypto/algif_skcipher.c
--- linux-libre-3.8-gnu1/crypto/algif_skcipher.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/algif_skcipher.c	2013-05-11 16:57:46.000000000 -0400
@@ -432,6 +432,7 @@ static int skcipher_recvmsg(struct kiocb
 	long copied = 0;
 
 	lock_sock(sk);
+	msg->msg_namelen = 0;
 	for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
 	     iovlen--, iov++) {
 		unsigned long seglen = iov->iov_len;
diff -druNp linux-libre-3.8-gnu1/crypto/blkcipher.c linux-libre-3.8.13-gnu1/crypto/blkcipher.c
--- linux-libre-3.8-gnu1/crypto/blkcipher.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/blkcipher.c	2013-05-11 16:57:46.000000000 -0400
@@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struc
 {
 	struct crypto_report_blkcipher rblkcipher;
 
-	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
-	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
-		 alg->cra_blkcipher.geniv ?: "<default>");
+	strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type));
+	strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "<default>",
+		sizeof(rblkcipher.geniv));
 
 	rblkcipher.blocksize = alg->cra_blocksize;
 	rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
diff -druNp linux-libre-3.8-gnu1/crypto/crypto_user.c linux-libre-3.8.13-gnu1/crypto/crypto_user.c
--- linux-libre-3.8-gnu1/crypto/crypto_user.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/crypto_user.c	2013-05-11 16:57:46.000000000 -0400
@@ -75,7 +75,7 @@ static int crypto_report_cipher(struct s
 {
 	struct crypto_report_cipher rcipher;
 
-	snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
+	strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
 
 	rcipher.blocksize = alg->cra_blocksize;
 	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
@@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_
 {
 	struct crypto_report_comp rcomp;
 
-	snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
-
+	strncpy(rcomp.type, "compression", sizeof(rcomp.type));
 	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
 		    sizeof(struct crypto_report_comp), &rcomp))
 		goto nla_put_failure;
@@ -108,12 +107,14 @@ nla_put_failure:
 static int crypto_report_one(struct crypto_alg *alg,
 			     struct crypto_user_alg *ualg, struct sk_buff *skb)
 {
-	memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
-	memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
-	       sizeof(ualg->cru_driver_name));
-	memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
-	       CRYPTO_MAX_ALG_NAME);
+	strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
+	strncpy(ualg->cru_driver_name, alg->cra_driver_name,
+		sizeof(ualg->cru_driver_name));
+	strncpy(ualg->cru_module_name, module_name(alg->cra_module),
+		sizeof(ualg->cru_module_name));
 
+	ualg->cru_type = 0;
+	ualg->cru_mask = 0;
 	ualg->cru_flags = alg->cra_flags;
 	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
 
@@ -122,8 +123,7 @@ static int crypto_report_one(struct cryp
 	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
 		struct crypto_report_larval rl;
 
-		snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
-
+		strncpy(rl.type, "larval", sizeof(rl.type));
 		if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
 			    sizeof(struct crypto_report_larval), &rl))
 			goto nla_put_failure;
diff -druNp linux-libre-3.8-gnu1/crypto/gcm.c linux-libre-3.8.13-gnu1/crypto/gcm.c
--- linux-libre-3.8-gnu1/crypto/gcm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/gcm.c	2013-05-11 16:57:46.000000000 -0400
@@ -44,6 +44,7 @@ struct crypto_rfc4543_ctx {
 
 struct crypto_rfc4543_req_ctx {
 	u8 auth_tag[16];
+	u8 assocbuf[32];
 	struct scatterlist cipher[1];
 	struct scatterlist payload[2];
 	struct scatterlist assoc[2];
@@ -1142,9 +1143,19 @@ static struct aead_request *crypto_rfc45
 	scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2);
 	assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);
 
-	sg_init_table(assoc, 2);
-	sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
-		    req->assoc->offset);
+	if (req->assoc->length == req->assoclen) {
+		sg_init_table(assoc, 2);
+		sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
+			    req->assoc->offset);
+	} else {
+		BUG_ON(req->assoclen > sizeof(rctx->assocbuf));
+
+		scatterwalk_map_and_copy(rctx->assocbuf, req->assoc, 0,
+					 req->assoclen, 0);
+
+		sg_init_table(assoc, 2);
+		sg_set_buf(assoc, rctx->assocbuf, req->assoclen);
+	}
 	scatterwalk_crypto_chain(assoc, payload, 0, 2);
 
 	aead_request_set_tfm(subreq, ctx->child);
diff -druNp linux-libre-3.8-gnu1/crypto/pcompress.c linux-libre-3.8.13-gnu1/crypto/pcompress.c
--- linux-libre-3.8-gnu1/crypto/pcompress.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/pcompress.c	2013-05-11 16:57:46.000000000 -0400
@@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk
 {
 	struct crypto_report_comp rpcomp;
 
-	snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
-
+	strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type));
 	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
 		    sizeof(struct crypto_report_comp), &rpcomp))
 		goto nla_put_failure;
diff -druNp linux-libre-3.8-gnu1/crypto/rng.c linux-libre-3.8.13-gnu1/crypto/rng.c
--- linux-libre-3.8-gnu1/crypto/rng.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/rng.c	2013-05-11 16:57:46.000000000 -0400
@@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_b
 {
 	struct crypto_report_rng rrng;
 
-	snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
+	strncpy(rrng.type, "rng", sizeof(rrng.type));
 
 	rrng.seedsize = alg->cra_rng.seedsize;
 
diff -druNp linux-libre-3.8-gnu1/crypto/shash.c linux-libre-3.8.13-gnu1/crypto/shash.c
--- linux-libre-3.8-gnu1/crypto/shash.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/crypto/shash.c	2013-05-11 16:57:46.000000000 -0400
@@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk
 	struct crypto_report_hash rhash;
 	struct shash_alg *salg = __crypto_shash_alg(alg);
 
-	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
+	strncpy(rhash.type, "shash", sizeof(rhash.type));
+
 	rhash.blocksize = alg->cra_blocksize;
 	rhash.digestsize = salg->digestsize;
 
diff -druNp linux-libre-3.8-gnu1/Documentation/devicetree/bindings/tty/serial/of-serial.txt linux-libre-3.8.13-gnu1/Documentation/devicetree/bindings/tty/serial/of-serial.txt
--- linux-libre-3.8-gnu1/Documentation/devicetree/bindings/tty/serial/of-serial.txt	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/Documentation/devicetree/bindings/tty/serial/of-serial.txt	2013-05-11 16:57:46.000000000 -0400
@@ -11,6 +11,9 @@ Required properties:
 	- "nvidia,tegra20-uart"
 	- "nxp,lpc3220-uart"
 	- "ibm,qpace-nwp-serial"
+	- "altr,16550-FIFO32"
+	- "altr,16550-FIFO64"
+	- "altr,16550-FIFO128"
 	- "serial" if the port type is unknown.
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
diff -druNp linux-libre-3.8-gnu1/Documentation/kernel-parameters.txt linux-libre-3.8.13-gnu1/Documentation/kernel-parameters.txt
--- linux-libre-3.8-gnu1/Documentation/kernel-parameters.txt	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/Documentation/kernel-parameters.txt	2013-05-11 16:57:46.000000000 -0400
@@ -564,6 +564,8 @@ bytes respectively. Such letter suffixes
 			UART at the specified I/O port or MMIO address,
 			switching to the matching ttyS device later.  The
 			options are the same as for ttyS, above.
+		hvc<n>	Use the hypervisor console device <n>. This is for
+			both Xen and PowerPC hypervisors.
 
                 If the device connected to the port is not a TTY but a braille
                 device, prepend "brl," before the device type, for instance
@@ -754,6 +756,7 @@ bytes respectively. Such letter suffixes
 
 	earlyprintk=	[X86,SH,BLACKFIN]
 			earlyprintk=vga
+			earlyprintk=xen
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
 			earlyprintk=dbgp[debugController#]
@@ -771,6 +774,8 @@ bytes respectively. Such letter suffixes
 			The VGA output is eventually overwritten by the real
 			console.
 
+			The xen output can only be used by Xen PV guests.
+
 	ekgdboc=	[X86,KGDB] Allow early kernel console debugging
 			ekgdboc=kbd
 
diff -druNp linux-libre-3.8-gnu1/drivers/acpi/glue.c linux-libre-3.8.13-gnu1/drivers/acpi/glue.c
--- linux-libre-3.8-gnu1/drivers/acpi/glue.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/acpi/glue.c	2013-05-11 16:57:46.000000000 -0400
@@ -95,40 +95,31 @@ static int acpi_find_bridge_device(struc
 	return ret;
 }
 
-/* Get device's handler per its address under its parent */
-struct acpi_find_child {
-	acpi_handle handle;
-	u64 address;
-};
-
-static acpi_status
-do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
+static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
+				      void *addr_p, void **ret_p)
 {
+	unsigned long long addr;
 	acpi_status status;
-	struct acpi_device_info *info;
-	struct acpi_find_child *find = context;
 
-	status = acpi_get_object_info(handle, &info);
-	if (ACPI_SUCCESS(status)) {
-		if ((info->address == find->address)
-			&& (info->valid & ACPI_VALID_ADR))
-			find->handle = handle;
-		kfree(info);
+	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
+	if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) {
+		*ret_p = handle;
+		return AE_CTRL_TERMINATE;
 	}
 	return AE_OK;
 }
 
 acpi_handle acpi_get_child(acpi_handle parent, u64 address)
 {
-	struct acpi_find_child find = { NULL, address };
+	void *ret = NULL;
 
 	if (!parent)
 		return NULL;
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, parent,
-			    1, do_acpi_find_child, NULL, &find, NULL);
-	return find.handle;
-}
 
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL,
+			    do_acpi_find_child, &address, &ret);
+	return (acpi_handle)ret;
+}
 EXPORT_SYMBOL(acpi_get_child);
 
 static int acpi_bind_one(struct device *dev, acpi_handle handle)
diff -druNp linux-libre-3.8-gnu1/drivers/acpi/Kconfig linux-libre-3.8.13-gnu1/drivers/acpi/Kconfig
--- linux-libre-3.8-gnu1/drivers/acpi/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/acpi/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -268,7 +268,8 @@ config ACPI_CUSTOM_DSDT
 	default ACPI_CUSTOM_DSDT_FILE != ""
 
 config ACPI_INITRD_TABLE_OVERRIDE
-	bool "ACPI tables can be passed via uncompressed cpio in initrd"
+	bool "ACPI tables override via initrd"
+	depends on BLK_DEV_INITRD && X86
 	default n
 	help
 	  This option provides functionality to override arbitrary ACPI tables
diff -druNp linux-libre-3.8-gnu1/drivers/acpi/osl.c linux-libre-3.8.13-gnu1/drivers/acpi/osl.c
--- linux-libre-3.8-gnu1/drivers/acpi/osl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/acpi/osl.c	2013-05-11 16:57:46.000000000 -0400
@@ -642,7 +642,7 @@ void __init acpi_initrd_override(void *d
 	 * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
 	 * works fine.
 	 */
-	memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
+	memblock_reserve(acpi_tables_addr, all_tables_size);
 	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
 	p = early_ioremap(acpi_tables_addr, all_tables_size);
diff -druNp linux-libre-3.8-gnu1/drivers/acpi/pci_root.c linux-libre-3.8.13-gnu1/drivers/acpi/pci_root.c
--- linux-libre-3.8-gnu1/drivers/acpi/pci_root.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/acpi/pci_root.c	2013-05-11 16:57:46.000000000 -0400
@@ -240,8 +240,8 @@ static acpi_status acpi_pci_query_osc(st
 		*control &= OSC_PCI_CONTROL_MASKS;
 		capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
 	} else {
-		/* Run _OSC query for all possible controls. */
-		capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
+		/* Run _OSC query only with existing controls. */
+		capbuf[OSC_CONTROL_TYPE] = root->osc_control_set;
 	}
 
 	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
@@ -454,7 +454,6 @@ static int acpi_pci_root_add(struct acpi
 	acpi_handle handle;
 	struct acpi_device *child;
 	u32 flags, base_flags;
-	bool is_osc_granted = false;
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
 	if (!root)
@@ -525,60 +524,6 @@ static int acpi_pci_root_add(struct acpi
 	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
 	acpi_pci_osc_support(root, flags);
 
-	/* Indicate support for various _OSC capabilities. */
-	if (pci_ext_cfg_avail())
-		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
-	if (pcie_aspm_support_enabled()) {
-		flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
-		OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
-	}
-	if (pci_msi_enabled())
-		flags |= OSC_MSI_SUPPORT;
-	if (flags != base_flags) {
-		status = acpi_pci_osc_support(root, flags);
-		if (ACPI_FAILURE(status)) {
-			dev_info(&device->dev, "ACPI _OSC support "
-				"notification failed, disabling PCIe ASPM\n");
-			pcie_no_aspm();
-			flags = base_flags;
-		}
-	}
-	if (!pcie_ports_disabled
-	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
-		flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
-			| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
-			| OSC_PCI_EXPRESS_PME_CONTROL;
-
-		if (pci_aer_available()) {
-			if (aer_acpi_firmware_first())
-				dev_dbg(&device->dev,
-					"PCIe errors handled by BIOS.\n");
-			else
-				flags |= OSC_PCI_EXPRESS_AER_CONTROL;
-		}
-
-		dev_info(&device->dev,
-			"Requesting ACPI _OSC control (0x%02x)\n", flags);
-
-		status = acpi_pci_osc_control_set(device->handle, &flags,
-				       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-		if (ACPI_SUCCESS(status)) {
-			is_osc_granted = true;
-			dev_info(&device->dev,
-				"ACPI _OSC control (0x%02x) granted\n", flags);
-		} else {
-			is_osc_granted = false;
-			dev_info(&device->dev,
-				"ACPI _OSC request failed (%s), "
-				"returned control mask: 0x%02x\n",
-				acpi_format_exception(status), flags);
-		}
-	} else {
-		dev_info(&device->dev,
-			"Unable to request _OSC control "
-			"(_OSC support mask: 0x%02x)\n", flags);
-	}
-
 	/*
 	 * TBD: Need PCI interface for enumeration/configuration of roots.
 	 */
@@ -618,14 +563,66 @@ static int acpi_pci_root_add(struct acpi
 	list_for_each_entry(child, &device->children, node)
 		acpi_pci_bridge_scan(child);
 
-	/* ASPM setting */
-	if (is_osc_granted) {
-		if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
-			pcie_clear_aspm(root->bus);
+	/* Indicate support for various _OSC capabilities. */
+	if (pci_ext_cfg_avail())
+		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
+	if (pcie_aspm_support_enabled())
+		flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
+			OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+	if (pci_msi_enabled())
+		flags |= OSC_MSI_SUPPORT;
+	if (flags != base_flags) {
+		status = acpi_pci_osc_support(root, flags);
+		if (ACPI_FAILURE(status)) {
+			dev_info(root->bus->bridge, "ACPI _OSC support "
+				"notification failed, disabling PCIe ASPM\n");
+			pcie_no_aspm();
+			flags = base_flags;
+		}
+	}
+
+	if (!pcie_ports_disabled
+	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
+		flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
+			| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
+			| OSC_PCI_EXPRESS_PME_CONTROL;
+
+		if (pci_aer_available()) {
+			if (aer_acpi_firmware_first())
+				dev_dbg(root->bus->bridge,
+					"PCIe errors handled by BIOS.\n");
+			else
+				flags |= OSC_PCI_EXPRESS_AER_CONTROL;
+		}
+
+		dev_info(root->bus->bridge,
+			"Requesting ACPI _OSC control (0x%02x)\n", flags);
+
+		status = acpi_pci_osc_control_set(device->handle, &flags,
+					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+		if (ACPI_SUCCESS(status)) {
+			dev_info(root->bus->bridge,
+				"ACPI _OSC control (0x%02x) granted\n", flags);
+			if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+				/*
+				 * We have ASPM control, but the FADT indicates
+				 * that it's unsupported. Clear it.
+				 */
+				pcie_clear_aspm(root->bus);
+			}
+		} else {
+			dev_info(root->bus->bridge,
+				"ACPI _OSC request failed (%s), "
+				"returned control mask: 0x%02x\n",
+				acpi_format_exception(status), flags);
+			pr_info("ACPI _OSC control for PCIe not granted, "
+				"disabling ASPM\n");
+			pcie_no_aspm();
+		}
 	} else {
-		pr_info("ACPI _OSC control for PCIe not granted, "
-			"disabling ASPM\n");
-		pcie_no_aspm();
+		dev_info(root->bus->bridge,
+			 "Unable to request _OSC control "
+			 "(_OSC support mask: 0x%02x)\n", flags);
 	}
 
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
diff -druNp linux-libre-3.8-gnu1/drivers/acpi/sleep.c linux-libre-3.8.13-gnu1/drivers/acpi/sleep.c
--- linux-libre-3.8-gnu1/drivers/acpi/sleep.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/acpi/sleep.c	2013-05-11 16:57:46.000000000 -0400
@@ -177,6 +177,14 @@ static struct dmi_system_id __initdata a
 	},
 	{
 	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-FW41E_H",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
 	.ident = "Sony Vaio VGN-FW21E",
 	.matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
diff -druNp linux-libre-3.8-gnu1/drivers/acpi/thermal.c linux-libre-3.8.13-gnu1/drivers/acpi/thermal.c
--- linux-libre-3.8-gnu1/drivers/acpi/thermal.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/acpi/thermal.c	2013-05-11 16:57:46.000000000 -0400
@@ -719,9 +719,19 @@ static int thermal_get_trend(struct ther
 		return -EINVAL;
 
 	if (type == THERMAL_TRIP_ACTIVE) {
-		/* aggressive active cooling */
-		*trend = THERMAL_TREND_RAISING;
-		return 0;
+		unsigned long trip_temp;
+		unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
+							tz->kelvin_offset);
+		if (thermal_get_trip_temp(thermal, trip, &trip_temp))
+			return -EINVAL;
+
+		if (temp > trip_temp) {
+			*trend = THERMAL_TREND_RAISING;
+			return 0;
+		} else {
+			/* Fall back on default trend */
+			return -EINVAL;
+		}
 	}
 
 	/*
diff -druNp linux-libre-3.8-gnu1/drivers/ata/ahci.c linux-libre-3.8.13-gnu1/drivers/ata/ahci.c
--- linux-libre-3.8-gnu1/drivers/ata/ahci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/ata/ahci.c	2013-05-11 16:57:46.000000000 -0400
@@ -265,6 +265,30 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
diff -druNp linux-libre-3.8-gnu1/drivers/ata/ata_piix.c linux-libre-3.8.13-gnu1/drivers/ata/ata_piix.c
--- linux-libre-3.8-gnu1/drivers/ata/ata_piix.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/ata/ata_piix.c	2013-05-11 16:57:46.000000000 -0400
@@ -150,6 +150,7 @@ enum piix_controller_ids {
 	tolapai_sata,
 	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
 	ich8_sata_snb,
+	ich8_2port_sata_snb,
 };
 
 struct piix_map_db {
@@ -304,7 +305,7 @@ static const struct pci_device_id piix_p
 	/* SATA Controller IDE (Lynx Point) */
 	{ 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (Lynx Point) */
-	{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
 	/* SATA Controller IDE (Lynx Point) */
 	{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (Lynx Point-LP) */
@@ -317,6 +318,23 @@ static const struct pci_device_id piix_p
 	{ 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (DH89xxCC) */
 	{ 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (Avoton) */
+	{ 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+	/* SATA Controller IDE (Avoton) */
+	{ 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+	/* SATA Controller IDE (Avoton) */
+	{ 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (Avoton) */
+	{ 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (Wellsburg) */
+	{ 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+	/* SATA Controller IDE (Wellsburg) */
+	{ 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (Wellsburg) */
+	{ 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+	/* SATA Controller IDE (Wellsburg) */
+	{ 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+
 	{ }	/* terminate list */
 };
 
@@ -422,6 +440,7 @@ static const struct piix_map_db *piix_ma
 	[ich8m_apple_sata]	= &ich8m_apple_map_db,
 	[tolapai_sata]		= &tolapai_map_db,
 	[ich8_sata_snb]		= &ich8_map_db,
+	[ich8_2port_sata_snb]	= &ich8_2port_map_db,
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -1223,6 +1242,16 @@ static struct ata_port_info piix_port_in
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &piix_sata_ops,
+	},
+
+	[ich8_2port_sata_snb] =
+	{
+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR
+					| PIIX_FLAG_PIO16,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 };
diff -druNp linux-libre-3.8-gnu1/drivers/ata/libata-acpi.c linux-libre-3.8.13-gnu1/drivers/ata/libata-acpi.c
--- linux-libre-3.8-gnu1/drivers/ata/libata-acpi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/ata/libata-acpi.c	2013-05-11 16:57:46.000000000 -0400
@@ -60,7 +60,8 @@ acpi_handle ata_ap_acpi_handle(struct at
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		return NULL;
 
-	return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no);
+	return ap->scsi_host ?
+		DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL;
 }
 EXPORT_SYMBOL(ata_ap_acpi_handle);
 
@@ -239,28 +240,15 @@ void ata_acpi_dissociate(struct ata_host
 	}
 }
 
-/**
- * ata_acpi_gtm - execute _GTM
- * @ap: target ATA port
- * @gtm: out parameter for _GTM result
- *
- * Evaluate _GTM and store the result in @gtm.
- *
- * LOCKING:
- * EH context.
- *
- * RETURNS:
- * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
- */
-int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
+static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
+			  struct ata_acpi_gtm *gtm)
 {
 	struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
 	union acpi_object *out_obj;
 	acpi_status status;
 	int rc = 0;
 
-	status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_GTM", NULL,
-				      &output);
+	status = acpi_evaluate_object(handle, "_GTM", NULL, &output);
 
 	rc = -ENOENT;
 	if (status == AE_NOT_FOUND)
@@ -294,6 +282,27 @@ int ata_acpi_gtm(struct ata_port *ap, st
 	return rc;
 }
 
+/**
+ * ata_acpi_gtm - execute _GTM
+ * @ap: target ATA port
+ * @gtm: out parameter for _GTM result
+ *
+ * Evaluate _GTM and store the result in @gtm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
+ */
+int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
+{
+	if (ata_ap_acpi_handle(ap))
+		return __ata_acpi_gtm(ap, ata_ap_acpi_handle(ap), gtm);
+	else
+		return -EINVAL;
+}
+
 EXPORT_SYMBOL_GPL(ata_acpi_gtm);
 
 /**
@@ -1095,7 +1104,7 @@ static int ata_acpi_bind_host(struct ata
 	if (!*handle)
 		return -ENODEV;
 
-	if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
+	if (__ata_acpi_gtm(ap, *handle, &ap->__acpi_init_gtm) == 0)
 		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
 
 	return 0;
diff -druNp linux-libre-3.8-gnu1/drivers/ata/libata-core.c linux-libre-3.8.13-gnu1/drivers/ata/libata-core.c
--- linux-libre-3.8-gnu1/drivers/ata/libata-core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/ata/libata-core.c	2013-05-11 16:57:46.000000000 -0400
@@ -2329,7 +2329,7 @@ int ata_dev_configure(struct ata_device
 		 * from SATA Settings page of Identify Device Data Log.
 		 */
 		if (ata_id_has_devslp(dev->id)) {
-			u8 sata_setting[ATA_SECT_SIZE];
+			u8 *sata_setting = ap->sector_buf;
 			int i, j;
 
 			dev->flags |= ATA_DFLAG_DEVSLP;
@@ -2437,6 +2437,9 @@ int ata_dev_configure(struct ata_device
 		dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
 					 dev->max_sectors);
 
+	if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48)
+		dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
 	if (ap->ops->dev_config)
 		ap->ops->dev_config(dev);
 
@@ -4098,6 +4101,7 @@ static const struct ata_blacklist_entry
 	/* Weird ATAPI devices */
 	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
 	{ "QUANTUM DAT    DAT72-000", NULL,	ATA_HORKAGE_ATAPI_MOD16_DMA },
+	{ "Slimtype DVD A  DS8A8SH", NULL,	ATA_HORKAGE_MAX_SEC_LBA48 },
 
 	/* Devices we expect to fail diagnostics */
 
diff -druNp linux-libre-3.8-gnu1/drivers/ata/sata_highbank.c linux-libre-3.8.13-gnu1/drivers/ata/sata_highbank.c
--- linux-libre-3.8-gnu1/drivers/ata/sata_highbank.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/ata/sata_highbank.c	2013-05-11 16:57:46.000000000 -0400
@@ -251,7 +251,7 @@ static const struct ata_port_info ahci_h
 };
 
 static struct scsi_host_template ahci_highbank_platform_sht = {
-	AHCI_SHT("highbank-ahci"),
+	AHCI_SHT("sata_highbank"),
 };
 
 static const struct of_device_id ahci_of_match[] = {
diff -druNp linux-libre-3.8-gnu1/drivers/base/bus.c linux-libre-3.8.13-gnu1/drivers/base/bus.c
--- linux-libre-3.8-gnu1/drivers/base/bus.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/base/bus.c	2013-05-11 16:57:46.000000000 -0400
@@ -290,7 +290,7 @@ int bus_for_each_dev(struct bus_type *bu
 	struct device *dev;
 	int error = 0;
 
-	if (!bus)
+	if (!bus || !bus->p)
 		return -EINVAL;
 
 	klist_iter_init_node(&bus->p->klist_devices, &i,
@@ -324,7 +324,7 @@ struct device *bus_find_device(struct bu
 	struct klist_iter i;
 	struct device *dev;
 
-	if (!bus)
+	if (!bus || !bus->p)
 		return NULL;
 
 	klist_iter_init_node(&bus->p->klist_devices, &i,
diff -druNp linux-libre-3.8-gnu1/drivers/base/dd.c linux-libre-3.8.13-gnu1/drivers/base/dd.c
--- linux-libre-3.8-gnu1/drivers/base/dd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/base/dd.c	2013-05-11 16:57:46.000000000 -0400
@@ -172,6 +172,8 @@ static int deferred_probe_initcall(void)
 
 	driver_deferred_probe_enable = true;
 	driver_deferred_probe_trigger();
+	/* Sort as many dependencies as possible before exiting initcalls */
+	flush_workqueue(deferred_wq);
 	return 0;
 }
 late_initcall(deferred_probe_initcall);
diff -druNp linux-libre-3.8-gnu1/drivers/base/regmap/regcache-rbtree.c linux-libre-3.8.13-gnu1/drivers/base/regmap/regcache-rbtree.c
--- linux-libre-3.8-gnu1/drivers/base/regmap/regcache-rbtree.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/base/regmap/regcache-rbtree.c	2013-05-11 16:57:46.000000000 -0400
@@ -398,7 +398,7 @@ static int regcache_rbtree_sync(struct r
 			base = 0;
 
 		if (max < rbnode->base_reg + rbnode->blklen)
-			end = rbnode->base_reg + rbnode->blklen - max;
+			end = max - rbnode->base_reg + 1;
 		else
 			end = rbnode->blklen;
 
diff -druNp linux-libre-3.8-gnu1/drivers/base/regmap/regmap.c linux-libre-3.8.13-gnu1/drivers/base/regmap/regmap.c
--- linux-libre-3.8-gnu1/drivers/base/regmap/regmap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/base/regmap/regmap.c	2013-05-11 16:57:46.000000000 -0400
@@ -662,12 +662,12 @@ struct regmap *regmap_init(struct device
 		}
 	}
 
+	regmap_debugfs_init(map, config->name);
+
 	ret = regcache_init(map, config);
 	if (ret != 0)
 		goto err_range;
 
-	regmap_debugfs_init(map, config->name);
-
 	/* Add a devres resource for dev_get_regmap() */
 	m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
 	if (!m) {
diff -druNp linux-libre-3.8-gnu1/drivers/block/aoe/aoecmd.c linux-libre-3.8.13-gnu1/drivers/block/aoe/aoecmd.c
--- linux-libre-3.8-gnu1/drivers/block/aoe/aoecmd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/aoe/aoecmd.c	2013-05-11 16:57:46.000000000 -0400
@@ -51,8 +51,9 @@ new_skb(ulong len)
 {
 	struct sk_buff *skb;
 
-	skb = alloc_skb(len, GFP_ATOMIC);
+	skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC);
 	if (skb) {
+		skb_reserve(skb, MAX_HEADER);
 		skb_reset_mac_header(skb);
 		skb_reset_network_header(skb);
 		skb->protocol = __constant_htons(ETH_P_AOE);
diff -druNp linux-libre-3.8-gnu1/drivers/block/loop.c linux-libre-3.8.13-gnu1/drivers/block/loop.c
--- linux-libre-3.8-gnu1/drivers/block/loop.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/loop.c	2013-05-11 16:57:46.000000000 -0400
@@ -917,6 +917,11 @@ static int loop_set_fd(struct loop_devic
 		lo->lo_flags |= LO_FLAGS_PARTSCAN;
 	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
+
+	/* Grab the block_device to prevent its destruction after we
+	 * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
+	 */
+	bdgrab(bdev);
 	return 0;
 
 out_clr:
@@ -1026,8 +1031,10 @@ static int loop_clr_fd(struct loop_devic
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
 	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
-	if (bdev)
+	if (bdev) {
+		bdput(bdev);
 		invalidate_bdev(bdev);
+	}
 	set_capacity(lo->lo_disk, 0);
 	loop_sysfs_exit(lo);
 	if (bdev) {
@@ -1285,11 +1292,9 @@ static int loop_set_capacity(struct loop
 	/* the width of sector_t may be narrow for bit-shift */
 	sz = sec;
 	sz <<= 9;
-	mutex_lock(&bdev->bd_mutex);
 	bd_set_size(bdev, sz);
 	/* let user-space know about the new size */
 	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
-	mutex_unlock(&bdev->bd_mutex);
 
  out:
 	return err;
@@ -1858,11 +1863,15 @@ static int __init loop_init(void)
 		max_part = (1UL << part_shift) - 1;
 	}
 
-	if ((1UL << part_shift) > DISK_MAX_PARTS)
-		return -EINVAL;
+	if ((1UL << part_shift) > DISK_MAX_PARTS) {
+		err = -EINVAL;
+		goto misc_out;
+	}
 
-	if (max_loop > 1UL << (MINORBITS - part_shift))
-		return -EINVAL;
+	if (max_loop > 1UL << (MINORBITS - part_shift)) {
+		err = -EINVAL;
+		goto misc_out;
+	}
 
 	/*
 	 * If max_loop is specified, create that many devices upfront.
@@ -1880,8 +1889,10 @@ static int __init loop_init(void)
 		range = 1UL << MINORBITS;
 	}
 
-	if (register_blkdev(LOOP_MAJOR, "loop"))
-		return -EIO;
+	if (register_blkdev(LOOP_MAJOR, "loop")) {
+		err = -EIO;
+		goto misc_out;
+	}
 
 	blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
 				  THIS_MODULE, loop_probe, NULL, NULL);
@@ -1894,6 +1905,10 @@ static int __init loop_init(void)
 
 	printk(KERN_INFO "loop: module loaded\n");
 	return 0;
+
+misc_out:
+	misc_deregister(&loop_misc);
+	return err;
 }
 
 static int loop_exit_cb(int id, void *ptr, void *data)
diff -druNp linux-libre-3.8-gnu1/drivers/block/nbd.c linux-libre-3.8.13-gnu1/drivers/block/nbd.c
--- linux-libre-3.8-gnu1/drivers/block/nbd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/nbd.c	2013-05-11 16:57:46.000000000 -0400
@@ -595,12 +595,20 @@ static int __nbd_ioctl(struct block_devi
 		struct request sreq;
 
 		dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
+		if (!nbd->sock)
+			return -EINVAL;
 
+		mutex_unlock(&nbd->tx_lock);
+		fsync_bdev(bdev);
+		mutex_lock(&nbd->tx_lock);
 		blk_rq_init(NULL, &sreq);
 		sreq.cmd_type = REQ_TYPE_SPECIAL;
 		nbd_cmd(&sreq) = NBD_CMD_DISC;
+
+		/* Check again after getting mutex back.  */
 		if (!nbd->sock)
 			return -EINVAL;
+
 		nbd_send_req(nbd, &sreq);
                 return 0;
 	}
@@ -614,6 +622,7 @@ static int __nbd_ioctl(struct block_devi
 		nbd_clear_que(nbd);
 		BUG_ON(!list_empty(&nbd->queue_head));
 		BUG_ON(!list_empty(&nbd->waiting_queue));
+		kill_bdev(bdev);
 		if (file)
 			fput(file);
 		return 0;
@@ -702,6 +711,7 @@ static int __nbd_ioctl(struct block_devi
 		nbd->file = NULL;
 		nbd_clear_que(nbd);
 		dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
+		kill_bdev(bdev);
 		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
 		if (file)
 			fput(file);
diff -druNp linux-libre-3.8-gnu1/drivers/block/xen-blkback/blkback.c linux-libre-3.8.13-gnu1/drivers/block/xen-blkback/blkback.c
--- linux-libre-3.8-gnu1/drivers/block/xen-blkback/blkback.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/xen-blkback/blkback.c	2013-05-11 16:57:46.000000000 -0400
@@ -46,6 +46,7 @@
 #include <xen/xen.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
+#include <xen/balloon.h>
 #include "common.h"
 
 /*
@@ -239,6 +240,7 @@ static void free_persistent_gnts(struct
 			ret = gnttab_unmap_refs(unmap, NULL, pages,
 				segs_to_unmap);
 			BUG_ON(ret);
+			free_xenballooned_pages(segs_to_unmap, pages);
 			segs_to_unmap = 0;
 		}
 
@@ -527,8 +529,8 @@ static int xen_blkbk_map(struct blkif_re
 				GFP_KERNEL);
 			if (!persistent_gnt)
 				return -ENOMEM;
-			persistent_gnt->page = alloc_page(GFP_KERNEL);
-			if (!persistent_gnt->page) {
+			if (alloc_xenballooned_pages(1, &persistent_gnt->page,
+			    false)) {
 				kfree(persistent_gnt);
 				return -ENOMEM;
 			}
@@ -677,6 +679,16 @@ static int dispatch_discard_io(struct xe
 	return err;
 }
 
+static int dispatch_other_io(struct xen_blkif *blkif,
+			     struct blkif_request *req,
+			     struct pending_req *pending_req)
+{
+	free_req(pending_req);
+	make_response(blkif, req->u.other.id, req->operation,
+		      BLKIF_RSP_EOPNOTSUPP);
+	return -EIO;
+}
+
 static void xen_blk_drain_io(struct xen_blkif *blkif)
 {
 	atomic_set(&blkif->drain, 1);
@@ -798,17 +810,30 @@ __do_block_io_op(struct xen_blkif *blkif
 
 		/* Apply all sanity checks to /private copy/ of request. */
 		barrier();
-		if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
+
+		switch (req.operation) {
+		case BLKIF_OP_READ:
+		case BLKIF_OP_WRITE:
+		case BLKIF_OP_WRITE_BARRIER:
+		case BLKIF_OP_FLUSH_DISKCACHE:
+			if (dispatch_rw_block_io(blkif, &req, pending_req))
+				goto done;
+			break;
+		case BLKIF_OP_DISCARD:
 			free_req(pending_req);
 			if (dispatch_discard_io(blkif, &req))
-				break;
-		} else if (dispatch_rw_block_io(blkif, &req, pending_req))
+				goto done;
+			break;
+		default:
+			if (dispatch_other_io(blkif, &req, pending_req))
+				goto done;
 			break;
+		}
 
 		/* Yield point for this unbounded loop. */
 		cond_resched();
 	}
-
+done:
 	return more_to_do;
 }
 
@@ -976,13 +1001,7 @@ static int dispatch_rw_block_io(struct x
 		bio->bi_end_io  = end_block_io_op;
 	}
 
-	/*
-	 * We set it one so that the last submit_bio does not have to call
-	 * atomic_inc.
-	 */
 	atomic_set(&pending_req->pendcnt, nbio);
-
-	/* Get a reference count for the disk queue and start sending I/O */
 	blk_start_plug(&plug);
 
 	for (i = 0; i < nbio; i++)
@@ -1010,6 +1029,7 @@ static int dispatch_rw_block_io(struct x
  fail_put_bio:
 	for (i = 0; i < nbio; i++)
 		bio_put(biolist[i]);
+	atomic_set(&pending_req->pendcnt, 1);
 	__end_block_io_op(pending_req, -EINVAL);
 	msleep(1); /* back off a bit */
 	return -EIO;
diff -druNp linux-libre-3.8-gnu1/drivers/block/xen-blkback/common.h linux-libre-3.8.13-gnu1/drivers/block/xen-blkback/common.h
--- linux-libre-3.8-gnu1/drivers/block/xen-blkback/common.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/xen-blkback/common.h	2013-05-11 16:57:46.000000000 -0400
@@ -77,11 +77,18 @@ struct blkif_x86_32_request_discard {
 	uint64_t       nr_sectors;
 } __attribute__((__packed__));
 
+struct blkif_x86_32_request_other {
+	uint8_t        _pad1;
+	blkif_vdev_t   _pad2;
+	uint64_t       id;           /* private guest value, echoed in resp  */
+} __attribute__((__packed__));
+
 struct blkif_x86_32_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	union {
 		struct blkif_x86_32_request_rw rw;
 		struct blkif_x86_32_request_discard discard;
+		struct blkif_x86_32_request_other other;
 	} u;
 } __attribute__((__packed__));
 
@@ -113,11 +120,19 @@ struct blkif_x86_64_request_discard {
 	uint64_t       nr_sectors;
 } __attribute__((__packed__));
 
+struct blkif_x86_64_request_other {
+	uint8_t        _pad1;
+	blkif_vdev_t   _pad2;
+	uint32_t       _pad3;        /* offsetof(blkif_..,u.discard.id)==8   */
+	uint64_t       id;           /* private guest value, echoed in resp  */
+} __attribute__((__packed__));
+
 struct blkif_x86_64_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	union {
 		struct blkif_x86_64_request_rw rw;
 		struct blkif_x86_64_request_discard discard;
+		struct blkif_x86_64_request_other other;
 	} u;
 } __attribute__((__packed__));
 
@@ -278,6 +293,11 @@ static inline void blkif_get_x86_32_req(
 		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
 		break;
 	default:
+		/*
+		 * Don't know how to translate this op. Only get the
+		 * ID so failure can be reported to the frontend.
+		 */
+		dst->u.other.id = src->u.other.id;
 		break;
 	}
 }
@@ -309,6 +329,11 @@ static inline void blkif_get_x86_64_req(
 		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
 		break;
 	default:
+		/*
+		 * Don't know how to translate this op. Only get the
+		 * ID so failure can be reported to the frontend.
+		 */
+		dst->u.other.id = src->u.other.id;
 		break;
 	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/block/xen-blkback/xenbus.c linux-libre-3.8.13-gnu1/drivers/block/xen-blkback/xenbus.c
--- linux-libre-3.8-gnu1/drivers/block/xen-blkback/xenbus.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/xen-blkback/xenbus.c	2013-05-11 16:57:46.000000000 -0400
@@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbu
 		be->blkif = NULL;
 	}
 
+	kfree(be->mode);
 	kfree(be);
 	dev_set_drvdata(&dev->dev, NULL);
 	return 0;
@@ -502,6 +503,7 @@ static void backend_changed(struct xenbu
 		= container_of(watch, struct backend_info, backend_watch);
 	struct xenbus_device *dev = be->dev;
 	int cdrom = 0;
+	unsigned long handle;
 	char *device_type;
 
 	DPRINTK("");
@@ -521,10 +523,10 @@ static void backend_changed(struct xenbu
 		return;
 	}
 
-	if ((be->major || be->minor) &&
-	    ((be->major != major) || (be->minor != minor))) {
-		pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n",
-			be->major, be->minor, major, minor);
+	if (be->major | be->minor) {
+		if (be->major != major || be->minor != minor)
+			pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n",
+				be->major, be->minor, major, minor);
 		return;
 	}
 
@@ -542,36 +544,33 @@ static void backend_changed(struct xenbu
 		kfree(device_type);
 	}
 
-	if (be->major == 0 && be->minor == 0) {
-		/* Front end dir is a number, which is used as the handle. */
-
-		char *p = strrchr(dev->otherend, '/') + 1;
-		long handle;
-		err = strict_strtoul(p, 0, &handle);
-		if (err)
-			return;
+	/* Front end dir is a number, which is used as the handle. */
+	err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
+	if (err)
+		return;
 
-		be->major = major;
-		be->minor = minor;
+	be->major = major;
+	be->minor = minor;
 
-		err = xen_vbd_create(be->blkif, handle, major, minor,
-				 (NULL == strchr(be->mode, 'w')), cdrom);
-		if (err) {
-			be->major = 0;
-			be->minor = 0;
-			xenbus_dev_fatal(dev, err, "creating vbd structure");
-			return;
-		}
+	err = xen_vbd_create(be->blkif, handle, major, minor,
+			     !strchr(be->mode, 'w'), cdrom);
 
+	if (err)
+		xenbus_dev_fatal(dev, err, "creating vbd structure");
+	else {
 		err = xenvbd_sysfs_addif(dev);
 		if (err) {
 			xen_vbd_free(&be->blkif->vbd);
-			be->major = 0;
-			be->minor = 0;
 			xenbus_dev_fatal(dev, err, "creating sysfs entries");
-			return;
 		}
+	}
 
+	if (err) {
+		kfree(be->mode);
+		be->mode = NULL;
+		be->major = 0;
+		be->minor = 0;
+	} else {
 		/* We're potentially connected now */
 		xen_update_blkif_status(be->blkif);
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/block/xen-blkfront.c linux-libre-3.8.13-gnu1/drivers/block/xen-blkfront.c
--- linux-libre-3.8-gnu1/drivers/block/xen-blkfront.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/block/xen-blkfront.c	2013-05-11 16:57:46.000000000 -0400
@@ -44,7 +44,7 @@
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
 #include <linux/bitmap.h>
-#include <linux/llist.h>
+#include <linux/list.h>
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -68,7 +68,7 @@ enum blkif_state {
 struct grant {
 	grant_ref_t gref;
 	unsigned long pfn;
-	struct llist_node node;
+	struct list_head node;
 };
 
 struct blk_shadow {
@@ -105,7 +105,7 @@ struct blkfront_info
 	struct work_struct work;
 	struct gnttab_free_callback callback;
 	struct blk_shadow shadow[BLK_RING_SIZE];
-	struct llist_head persistent_gnts;
+	struct list_head persistent_gnts;
 	unsigned int persistent_gnts_c;
 	unsigned long shadow_free;
 	unsigned int feature_flush;
@@ -371,10 +371,11 @@ static int blkif_queue_request(struct re
 			lsect = fsect + (sg->length >> 9) - 1;
 
 			if (info->persistent_gnts_c) {
-				BUG_ON(llist_empty(&info->persistent_gnts));
-				gnt_list_entry = llist_entry(
-					llist_del_first(&info->persistent_gnts),
-					struct grant, node);
+				BUG_ON(list_empty(&info->persistent_gnts));
+				gnt_list_entry = list_first_entry(
+				                      &info->persistent_gnts,
+				                      struct grant, node);
+				list_del(&gnt_list_entry->node);
 
 				ref = gnt_list_entry->gref;
 				buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn);
@@ -790,9 +791,8 @@ static void blkif_restart_queue(struct w
 
 static void blkif_free(struct blkfront_info *info, int suspend)
 {
-	struct llist_node *all_gnts;
 	struct grant *persistent_gnt;
-	struct llist_node *n;
+	struct grant *n;
 
 	/* Prevent new requests being issued until we fix things up. */
 	spin_lock_irq(&info->io_lock);
@@ -804,13 +804,15 @@ static void blkif_free(struct blkfront_i
 
 	/* Remove all persistent grants */
 	if (info->persistent_gnts_c) {
-		all_gnts = llist_del_all(&info->persistent_gnts);
-		llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) {
+		list_for_each_entry_safe(persistent_gnt, n,
+		                         &info->persistent_gnts, node) {
+			list_del(&persistent_gnt->node);
 			gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
 			__free_page(pfn_to_page(persistent_gnt->pfn));
 			kfree(persistent_gnt);
+			info->persistent_gnts_c--;
 		}
-		info->persistent_gnts_c = 0;
+		BUG_ON(info->persistent_gnts_c != 0);
 	}
 
 	/* No more gnttab callback work. */
@@ -868,7 +870,7 @@ static void blkif_completion(struct blk_
 	}
 	/* Add the persistent grant into the list of free grants */
 	for (i = 0; i < s->req.u.rw.nr_segments; i++) {
-		llist_add(&s->grants_used[i]->node, &info->persistent_gnts);
+		list_add(&s->grants_used[i]->node, &info->persistent_gnts);
 		info->persistent_gnts_c++;
 	}
 }
@@ -1164,7 +1166,7 @@ static int blkfront_probe(struct xenbus_
 	spin_lock_init(&info->io_lock);
 	info->xbdev = dev;
 	info->vdevice = vdevice;
-	init_llist_head(&info->persistent_gnts);
+	INIT_LIST_HEAD(&info->persistent_gnts);
 	info->persistent_gnts_c = 0;
 	info->connected = BLKIF_STATE_DISCONNECTED;
 	INIT_WORK(&info->work, blkif_restart_queue);
diff -druNp linux-libre-3.8-gnu1/drivers/bluetooth/ath3k.c linux-libre-3.8.13-gnu1/drivers/bluetooth/ath3k.c
--- linux-libre-3.8-gnu1/drivers/bluetooth/ath3k.c	2013-05-01 16:46:35.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/bluetooth/ath3k.c	2013-05-11 19:22:24.000000000 -0400
@@ -73,8 +73,10 @@ static struct usb_device_id ath3k_table[
 	{ USB_DEVICE(0x03F0, 0x311D) },
 
 	/* Atheros AR3012 with sflash firmware*/
+	{ USB_DEVICE(0x0CF3, 0x0036) },
 	{ USB_DEVICE(0x0CF3, 0x3004) },
 	{ USB_DEVICE(0x0CF3, 0x311D) },
+	{ USB_DEVICE(0x0CF3, 0x817a) },
 	{ USB_DEVICE(0x13d3, 0x3375) },
 	{ USB_DEVICE(0x04CA, 0x3005) },
 	{ USB_DEVICE(0x04CA, 0x3006) },
@@ -105,8 +107,10 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
 static struct usb_device_id ath3k_blist_tbl[] = {
 
 	/* Atheros AR3012 with sflash firmware*/
+	{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
diff -druNp linux-libre-3.8-gnu1/drivers/bluetooth/btusb.c linux-libre-3.8.13-gnu1/drivers/bluetooth/btusb.c
--- linux-libre-3.8-gnu1/drivers/bluetooth/btusb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/bluetooth/btusb.c	2013-05-11 16:57:46.000000000 -0400
@@ -131,8 +131,10 @@ static struct usb_device_id blacklist_ta
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros 3012 with sflash firmware */
+	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
diff -druNp linux-libre-3.8-gnu1/drivers/char/hpet.c linux-libre-3.8.13-gnu1/drivers/char/hpet.c
--- linux-libre-3.8-gnu1/drivers/char/hpet.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/hpet.c	2013-05-11 16:57:46.000000000 -0400
@@ -373,26 +373,14 @@ static int hpet_mmap(struct file *file,
 	struct hpet_dev *devp;
 	unsigned long addr;
 
-	if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
-		return -EINVAL;
-
 	devp = file->private_data;
 	addr = devp->hd_hpets->hp_hpet_phys;
 
 	if (addr & (PAGE_SIZE - 1))
 		return -ENOSYS;
 
-	vma->vm_flags |= VM_IO;
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
-					PAGE_SIZE, vma->vm_page_prot)) {
-		printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
-			__func__);
-		return -EAGAIN;
-	}
-
-	return 0;
+	return vm_iomap_memory(vma, addr, PAGE_SIZE);
 #else
 	return -ENOSYS;
 #endif
diff -druNp linux-libre-3.8-gnu1/drivers/char/hw_random/core.c linux-libre-3.8.13-gnu1/drivers/char/hw_random/core.c
--- linux-libre-3.8-gnu1/drivers/char/hw_random/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/hw_random/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -40,6 +40,7 @@
 #include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 
 
@@ -52,8 +53,12 @@ static struct hwrng *current_rng;
 static LIST_HEAD(rng_list);
 static DEFINE_MUTEX(rng_mutex);
 static int data_avail;
-static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES]
-	__cacheline_aligned;
+static u8 *rng_buffer;
+
+static size_t rng_buffer_size(void)
+{
+	return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
+}
 
 static inline int hwrng_init(struct hwrng *rng)
 {
@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file
 
 		if (!data_avail) {
 			bytes_read = rng_get_data(current_rng, rng_buffer,
-				sizeof(rng_buffer),
+				rng_buffer_size(),
 				!(filp->f_flags & O_NONBLOCK));
 			if (bytes_read < 0) {
 				err = bytes_read;
@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng)
 
 	mutex_lock(&rng_mutex);
 
+	/* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
+	err = -ENOMEM;
+	if (!rng_buffer) {
+		rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
+		if (!rng_buffer)
+			goto out_unlock;
+	}
+
 	/* Must not register two RNGs with the same name. */
 	err = -EEXIST;
 	list_for_each_entry(tmp, &rng_list, list) {
diff -druNp linux-libre-3.8-gnu1/drivers/char/hw_random/virtio-rng.c linux-libre-3.8.13-gnu1/drivers/char/hw_random/virtio-rng.c
--- linux-libre-3.8-gnu1/drivers/char/hw_random/virtio-rng.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/hw_random/virtio-rng.c	2013-05-11 16:57:46.000000000 -0400
@@ -92,14 +92,22 @@ static int probe_common(struct virtio_de
 {
 	int err;
 
+	if (vq) {
+		/* We only support one device for now */
+		return -EBUSY;
+	}
 	/* We expect a single virtqueue. */
 	vq = virtio_find_single_vq(vdev, random_recv_done, "input");
-	if (IS_ERR(vq))
-		return PTR_ERR(vq);
+	if (IS_ERR(vq)) {
+		err = PTR_ERR(vq);
+		vq = NULL;
+		return err;
+	}
 
 	err = hwrng_register(&virtio_hwrng);
 	if (err) {
 		vdev->config->del_vqs(vdev);
+		vq = NULL;
 		return err;
 	}
 
@@ -112,6 +120,7 @@ static void remove_common(struct virtio_
 	busy = false;
 	hwrng_unregister(&virtio_hwrng);
 	vdev->config->del_vqs(vdev);
+	vq = NULL;
 }
 
 static int virtrng_probe(struct virtio_device *vdev)
diff -druNp linux-libre-3.8-gnu1/drivers/char/random.c linux-libre-3.8.13-gnu1/drivers/char/random.c
--- linux-libre-3.8-gnu1/drivers/char/random.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/random.c	2013-05-11 16:57:46.000000000 -0400
@@ -852,6 +852,7 @@ static size_t account(struct entropy_sto
 		      int reserved)
 {
 	unsigned long flags;
+	int wakeup_write = 0;
 
 	/* Hold lock while accounting */
 	spin_lock_irqsave(&r->lock, flags);
@@ -873,10 +874,8 @@ static size_t account(struct entropy_sto
 		else
 			r->entropy_count = reserved;
 
-		if (r->entropy_count < random_write_wakeup_thresh) {
-			wake_up_interruptible(&random_write_wait);
-			kill_fasync(&fasync, SIGIO, POLL_OUT);
-		}
+		if (r->entropy_count < random_write_wakeup_thresh)
+			wakeup_write = 1;
 	}
 
 	DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
@@ -884,6 +883,11 @@ static size_t account(struct entropy_sto
 
 	spin_unlock_irqrestore(&r->lock, flags);
 
+	if (wakeup_write) {
+		wake_up_interruptible(&random_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+
 	return nbytes;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/char/tpm/tpm.c linux-libre-3.8.13-gnu1/drivers/char/tpm/tpm.c
--- linux-libre-3.8-gnu1/drivers/char/tpm/tpm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/tpm/tpm.c	2013-05-11 16:57:46.000000000 -0400
@@ -1291,7 +1291,7 @@ int tpm_pm_suspend(struct device *dev)
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 	struct tpm_cmd_t cmd;
-	int rc;
+	int rc, try;
 
 	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
 
@@ -1309,9 +1309,32 @@ int tpm_pm_suspend(struct device *dev)
 	}
 
 	/* now do the actual savestate */
-	cmd.header.in = savestate_header;
-	rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
-			  "sending savestate before suspend");
+	for (try = 0; try < TPM_RETRY; try++) {
+		cmd.header.in = savestate_header;
+		rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
+
+		/*
+		 * If the TPM indicates that it is too busy to respond to
+		 * this command then retry before giving up.  It can take
+		 * several seconds for this TPM to be ready.
+		 *
+		 * This can happen if the TPM has already been sent the
+		 * SaveState command before the driver has loaded.  TCG 1.2
+		 * specification states that any communication after SaveState
+		 * may cause the TPM to invalidate previously saved state.
+		 */
+		if (rc != TPM_WARN_RETRY)
+			break;
+		msleep(TPM_TIMEOUT_RETRY);
+	}
+
+	if (rc)
+		dev_err(chip->dev,
+			"Error (%d) sending savestate before suspend\n", rc);
+	else if (try > 0)
+		dev_warn(chip->dev, "TPM savestate took %dms\n",
+			 try * TPM_TIMEOUT_RETRY);
+
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pm_suspend);
diff -druNp linux-libre-3.8-gnu1/drivers/char/tpm/tpm.h linux-libre-3.8.13-gnu1/drivers/char/tpm/tpm.h
--- linux-libre-3.8-gnu1/drivers/char/tpm/tpm.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/tpm/tpm.h	2013-05-11 16:57:46.000000000 -0400
@@ -32,10 +32,12 @@ enum tpm_const {
 	TPM_MINOR = 224,	/* officially assigned */
 	TPM_BUFSIZE = 4096,
 	TPM_NUM_DEVICES = 256,
+	TPM_RETRY = 50,		/* 5 seconds */
 };
 
 enum tpm_timeout {
 	TPM_TIMEOUT = 5,	/* msecs */
+	TPM_TIMEOUT_RETRY = 100 /* msecs */
 };
 
 /* TPM addresses */
@@ -44,6 +46,7 @@ enum tpm_addr {
 	TPM_ADDR = 0x4E,
 };
 
+#define TPM_WARN_RETRY          0x800
 #define TPM_WARN_DOING_SELFTEST 0x802
 #define TPM_ERR_DEACTIVATED     0x6
 #define TPM_ERR_DISABLED        0x7
diff -druNp linux-libre-3.8-gnu1/drivers/char/virtio_console.c linux-libre-3.8.13-gnu1/drivers/char/virtio_console.c
--- linux-libre-3.8-gnu1/drivers/char/virtio_console.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/char/virtio_console.c	2013-05-11 16:57:46.000000000 -0400
@@ -152,7 +152,8 @@ struct ports_device {
 	spinlock_t ports_lock;
 
 	/* To protect the vq operations for the control channel */
-	spinlock_t cvq_lock;
+	spinlock_t c_ivq_lock;
+	spinlock_t c_ovq_lock;
 
 	/* The current config space is stored here */
 	struct virtio_console_config config;
@@ -575,11 +576,14 @@ static ssize_t __send_control_msg(struct
 	vq = portdev->c_ovq;
 
 	sg_init_one(sg, &cpkt, sizeof(cpkt));
+
+	spin_lock(&portdev->c_ovq_lock);
 	if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
 		virtqueue_kick(vq);
 		while (!virtqueue_get_buf(vq, &len))
 			cpu_relax();
 	}
+	spin_unlock(&portdev->c_ovq_lock);
 	return 0;
 }
 
@@ -1715,23 +1719,23 @@ static void control_work_handler(struct
 	portdev = container_of(work, struct ports_device, control_work);
 	vq = portdev->c_ivq;
 
-	spin_lock(&portdev->cvq_lock);
+	spin_lock(&portdev->c_ivq_lock);
 	while ((buf = virtqueue_get_buf(vq, &len))) {
-		spin_unlock(&portdev->cvq_lock);
+		spin_unlock(&portdev->c_ivq_lock);
 
 		buf->len = len;
 		buf->offset = 0;
 
 		handle_control_message(portdev, buf);
 
-		spin_lock(&portdev->cvq_lock);
+		spin_lock(&portdev->c_ivq_lock);
 		if (add_inbuf(portdev->c_ivq, buf) < 0) {
 			dev_warn(&portdev->vdev->dev,
 				 "Error adding buffer to queue\n");
 			free_buf(buf, false);
 		}
 	}
-	spin_unlock(&portdev->cvq_lock);
+	spin_unlock(&portdev->c_ivq_lock);
 }
 
 static void out_intr(struct virtqueue *vq)
@@ -1996,10 +2000,12 @@ static int virtcons_probe(struct virtio_
 	if (multiport) {
 		unsigned int nr_added_bufs;
 
-		spin_lock_init(&portdev->cvq_lock);
+		spin_lock_init(&portdev->c_ivq_lock);
+		spin_lock_init(&portdev->c_ovq_lock);
 		INIT_WORK(&portdev->control_work, &control_work_handler);
 
-		nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+		nr_added_bufs = fill_queue(portdev->c_ivq,
+					   &portdev->c_ivq_lock);
 		if (!nr_added_bufs) {
 			dev_err(&vdev->dev,
 				"Error allocating buffers for control queue\n");
@@ -2150,7 +2156,7 @@ static int virtcons_restore(struct virti
 		return ret;
 
 	if (use_multiport(portdev))
-		fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+		fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
 
 	list_for_each_entry(port, &portdev->ports, list) {
 		port->in_vq = portdev->in_vqs[port->id];
diff -druNp linux-libre-3.8-gnu1/drivers/connector/cn_proc.c linux-libre-3.8.13-gnu1/drivers/connector/cn_proc.c
--- linux-libre-3.8-gnu1/drivers/connector/cn_proc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/connector/cn_proc.c	2013-05-11 16:57:46.000000000 -0400
@@ -313,6 +313,12 @@ static void cn_proc_mcast_ctl(struct cn_
 	    (task_active_pid_ns(current) != &init_pid_ns))
 		return;
 
+	/* Can only change if privileged. */
+	if (!capable(CAP_NET_ADMIN)) {
+		err = EPERM;
+		goto out;
+	}
+
 	mc_op = (enum proc_cn_mcast_op *)msg->data;
 	switch (*mc_op) {
 	case PROC_CN_MCAST_LISTEN:
@@ -325,6 +331,8 @@ static void cn_proc_mcast_ctl(struct cn_
 		err = EINVAL;
 		break;
 	}
+
+out:
 	cn_proc_ack(err, msg->seq, msg->ack);
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/cpufreq/exynos-cpufreq.c linux-libre-3.8.13-gnu1/drivers/cpufreq/exynos-cpufreq.c
--- linux-libre-3.8-gnu1/drivers/cpufreq/exynos-cpufreq.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/cpufreq/exynos-cpufreq.c	2013-05-11 16:57:46.000000000 -0400
@@ -222,8 +222,6 @@ static int exynos_cpufreq_cpu_init(struc
 
 	cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
 
-	locking_frequency = exynos_getspeed(0);
-
 	/* set the transition latency value */
 	policy->cpuinfo.transition_latency = 100000;
 
@@ -288,6 +286,8 @@ static int __init exynos_cpufreq_init(vo
 		goto err_vdd_arm;
 	}
 
+	locking_frequency = exynos_getspeed(0);
+
 	register_pm_notifier(&exynos_cpufreq_nb);
 
 	if (cpufreq_register_driver(&exynos_driver)) {
diff -druNp linux-libre-3.8-gnu1/drivers/crypto/caam/caamalg.c linux-libre-3.8.13-gnu1/drivers/crypto/caam/caamalg.c
--- linux-libre-3.8-gnu1/drivers/crypto/caam/caamalg.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/crypto/caam/caamalg.c	2013-05-11 16:57:46.000000000 -0400
@@ -1650,11 +1650,7 @@ struct caam_alg_template {
 };
 
 static struct caam_alg_template driver_algs[] = {
-	/*
-	 * single-pass ipsec_esp descriptor
-	 * authencesn(*,*) is also registered, although not present
-	 * explicitly here.
-	 */
+	/* single-pass ipsec_esp descriptor */
 	{
 		.name = "authenc(hmac(md5),cbc(aes))",
 		.driver_name = "authenc-hmac-md5-cbc-aes-caam",
@@ -2217,9 +2213,7 @@ static int __init caam_algapi_init(void)
 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
 		/* TODO: check if h/w supports alg */
 		struct caam_crypto_alg *t_alg;
-		bool done = false;
 
-authencesn:
 		t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
 		if (IS_ERR(t_alg)) {
 			err = PTR_ERR(t_alg);
@@ -2233,25 +2227,8 @@ authencesn:
 			dev_warn(ctrldev, "%s alg registration failed\n",
 				t_alg->crypto_alg.cra_driver_name);
 			kfree(t_alg);
-		} else {
+		} else
 			list_add_tail(&t_alg->entry, &priv->alg_list);
-			if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD &&
-			    !memcmp(driver_algs[i].name, "authenc", 7) &&
-			    !done) {
-				char *name;
-
-				name = driver_algs[i].name;
-				memmove(name + 10, name + 7, strlen(name) - 7);
-				memcpy(name + 7, "esn", 3);
-
-				name = driver_algs[i].driver_name;
-				memmove(name + 10, name + 7, strlen(name) - 7);
-				memcpy(name + 7, "esn", 3);
-
-				done = true;
-				goto authencesn;
-			}
-		}
 	}
 	if (!list_empty(&priv->alg_list))
 		dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
diff -druNp linux-libre-3.8-gnu1/drivers/crypto/caam/compat.h linux-libre-3.8.13-gnu1/drivers/crypto/caam/compat.h
--- linux-libre-3.8-gnu1/drivers/crypto/caam/compat.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/crypto/caam/compat.h	2013-05-11 16:57:46.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/types.h>
 #include <linux/debugfs.h>
 #include <linux/circ_buf.h>
-#include <linux/string.h>
 #include <net/xfrm.h>
 
 #include <crypto/algapi.h>
diff -druNp linux-libre-3.8-gnu1/drivers/crypto/talitos.c linux-libre-3.8.13-gnu1/drivers/crypto/talitos.c
--- linux-libre-3.8-gnu1/drivers/crypto/talitos.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/crypto/talitos.c	2013-05-11 16:57:46.000000000 -0400
@@ -38,7 +38,6 @@
 #include <linux/spinlock.h>
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
-#include <linux/string.h>
 
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
@@ -1974,11 +1973,7 @@ struct talitos_alg_template {
 };
 
 static struct talitos_alg_template driver_algs[] = {
-	/*
-	 * AEAD algorithms. These use a single-pass ipsec_esp descriptor.
-	 * authencesn(*,*) is also registered, although not present
-	 * explicitly here.
-	 */
+	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
 	{	.type = CRYPTO_ALG_TYPE_AEAD,
 		.alg.crypto = {
 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
@@ -2820,9 +2815,7 @@ static int talitos_probe(struct platform
 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
 			struct talitos_crypto_alg *t_alg;
 			char *name = NULL;
-			bool authenc = false;
 
-authencesn:
 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
 			if (IS_ERR(t_alg)) {
 				err = PTR_ERR(t_alg);
@@ -2837,8 +2830,6 @@ authencesn:
 				err = crypto_register_alg(
 						&t_alg->algt.alg.crypto);
 				name = t_alg->algt.alg.crypto.cra_driver_name;
-				authenc = authenc ? !authenc :
-					  !(bool)memcmp(name, "authenc", 7);
 				break;
 			case CRYPTO_ALG_TYPE_AHASH:
 				err = crypto_register_ahash(
@@ -2851,25 +2842,8 @@ authencesn:
 				dev_err(dev, "%s alg registration failed\n",
 					name);
 				kfree(t_alg);
-			} else {
+			} else
 				list_add_tail(&t_alg->entry, &priv->alg_list);
-				if (authenc) {
-					struct crypto_alg *alg =
-						&driver_algs[i].alg.crypto;
-
-					name = alg->cra_name;
-					memmove(name + 10, name + 7,
-						strlen(name) - 7);
-					memcpy(name + 7, "esn", 3);
-
-					name = alg->cra_driver_name;
-					memmove(name + 10, name + 7,
-						strlen(name) - 7);
-					memcpy(name + 7, "esn", 3);
-
-					goto authencesn;
-				}
-			}
 		}
 	}
 	if (!list_empty(&priv->alg_list))
diff -druNp linux-libre-3.8-gnu1/drivers/crypto/ux500/cryp/cryp_core.c linux-libre-3.8.13-gnu1/drivers/crypto/ux500/cryp/cryp_core.c
--- linux-libre-3.8-gnu1/drivers/crypto/ux500/cryp/cryp_core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/crypto/ux500/cryp/cryp_core.c	2013-05-11 16:57:46.000000000 -0400
@@ -1750,7 +1750,7 @@ static struct platform_driver cryp_drive
 	.shutdown = ux500_cryp_shutdown,
 	.driver = {
 		.owner = THIS_MODULE,
-		.name  = "cryp1"
+		.name  = "cryp1",
 		.pm    = &ux500_cryp_pm,
 	}
 };
diff -druNp linux-libre-3.8-gnu1/drivers/dca/dca-core.c linux-libre-3.8.13-gnu1/drivers/dca/dca-core.c
--- linux-libre-3.8-gnu1/drivers/dca/dca-core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/dca/dca-core.c	2013-05-11 16:57:46.000000000 -0400
@@ -420,6 +420,11 @@ void unregister_dca_provider(struct dca_
 
 	raw_spin_lock_irqsave(&dca_lock, flags);
 
+	if (list_empty(&dca_domains)) {
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
+		return;
+	}
+
 	list_del(&dca->node);
 
 	pci_rc = dca_pci_rc_from_dev(dev);
diff -druNp linux-libre-3.8-gnu1/drivers/dma/omap-dma.c linux-libre-3.8.13-gnu1/drivers/dma/omap-dma.c
--- linux-libre-3.8-gnu1/drivers/dma/omap-dma.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/dma/omap-dma.c	2013-05-11 16:57:46.000000000 -0400
@@ -276,12 +276,20 @@ static void omap_dma_issue_pending(struc
 
 	spin_lock_irqsave(&c->vc.lock, flags);
 	if (vchan_issue_pending(&c->vc) && !c->desc) {
-		struct omap_dmadev *d = to_omap_dma_dev(chan->device);
-		spin_lock(&d->lock);
-		if (list_empty(&c->node))
-			list_add_tail(&c->node, &d->pending);
-		spin_unlock(&d->lock);
-		tasklet_schedule(&d->task);
+		/*
+		 * c->cyclic is used only by audio and in this case the DMA need
+		 * to be started without delay.
+		 */
+		if (!c->cyclic) {
+			struct omap_dmadev *d = to_omap_dma_dev(chan->device);
+			spin_lock(&d->lock);
+			if (list_empty(&c->node))
+				list_add_tail(&c->node, &d->pending);
+			spin_unlock(&d->lock);
+			tasklet_schedule(&d->task);
+		} else {
+			omap_dma_start_desc(c);
+		}
 	}
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 }
diff -druNp linux-libre-3.8-gnu1/drivers/dma/sh/shdma.c linux-libre-3.8.13-gnu1/drivers/dma/sh/shdma.c
--- linux-libre-3.8-gnu1/drivers/dma/sh/shdma.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/dma/sh/shdma.c	2013-05-11 16:57:46.000000000 -0400
@@ -326,7 +326,7 @@ static int sh_dmae_set_slave(struct shdm
 						    shdma_chan);
 	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id);
 	if (!cfg)
-		return -ENODEV;
+		return -ENXIO;
 
 	if (!try)
 		sh_chan->config = cfg;
diff -druNp linux-libre-3.8-gnu1/drivers/edac/edac_mc_sysfs.c linux-libre-3.8.13-gnu1/drivers/edac/edac_mc_sysfs.c
--- linux-libre-3.8-gnu1/drivers/edac/edac_mc_sysfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/edac/edac_mc_sysfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -330,17 +330,17 @@ static struct device_attribute *dynamic_
 };
 
 /* possible dynamic channel ce_count attribute files */
-DEVICE_CHANNEL(ch0_ce_count, S_IRUGO | S_IWUSR,
+DEVICE_CHANNEL(ch0_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 0);
-DEVICE_CHANNEL(ch1_ce_count, S_IRUGO | S_IWUSR,
+DEVICE_CHANNEL(ch1_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 1);
-DEVICE_CHANNEL(ch2_ce_count, S_IRUGO | S_IWUSR,
+DEVICE_CHANNEL(ch2_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 2);
-DEVICE_CHANNEL(ch3_ce_count, S_IRUGO | S_IWUSR,
+DEVICE_CHANNEL(ch3_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 3);
-DEVICE_CHANNEL(ch4_ce_count, S_IRUGO | S_IWUSR,
+DEVICE_CHANNEL(ch4_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 4);
-DEVICE_CHANNEL(ch5_ce_count, S_IRUGO | S_IWUSR,
+DEVICE_CHANNEL(ch5_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 5);
 
 /* Total possible dynamic ce_count attribute file table */
diff -druNp linux-libre-3.8-gnu1/drivers/eisa/pci_eisa.c linux-libre-3.8.13-gnu1/drivers/eisa/pci_eisa.c
--- linux-libre-3.8-gnu1/drivers/eisa/pci_eisa.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/eisa/pci_eisa.c	2013-05-11 16:57:46.000000000 -0400
@@ -19,10 +19,10 @@
 /* There is only *one* pci_eisa device per machine, right ? */
 static struct eisa_root_device pci_eisa_root;
 
-static int __init pci_eisa_init(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
+static int __init pci_eisa_init(struct pci_dev *pdev)
 {
-	int rc;
+	int rc, i;
+	struct resource *res, *bus_res = NULL;
 
 	if ((rc = pci_enable_device (pdev))) {
 		printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
@@ -30,9 +30,30 @@ static int __init pci_eisa_init(struct p
 		return rc;
 	}
 
+	/*
+	 * The Intel 82375 PCI-EISA bridge is a subtractive-decode PCI
+	 * device, so the resources available on EISA are the same as those
+	 * available on the 82375 bus.  This works the same as a PCI-PCI
+	 * bridge in subtractive-decode mode (see pci_read_bridge_bases()).
+	 * We assume other PCI-EISA bridges are similar.
+	 *
+	 * eisa_root_register() can only deal with a single io port resource,
+	*  so we use the first valid io port resource.
+	 */
+	pci_bus_for_each_resource(pdev->bus, res, i)
+		if (res && (res->flags & IORESOURCE_IO)) {
+			bus_res = res;
+			break;
+		}
+
+	if (!bus_res) {
+		dev_err(&pdev->dev, "No resources available\n");
+		return -1;
+	}
+
 	pci_eisa_root.dev              = &pdev->dev;
-	pci_eisa_root.res	       = pdev->bus->resource[0];
-	pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
+	pci_eisa_root.res	       = bus_res;
+	pci_eisa_root.bus_base_addr    = bus_res->start;
 	pci_eisa_root.slots	       = EISA_MAX_SLOTS;
 	pci_eisa_root.dma_mask         = pdev->dma_mask;
 	dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root);
@@ -45,22 +66,26 @@ static int __init pci_eisa_init(struct p
 	return 0;
 }
 
-static struct pci_device_id pci_eisa_pci_tbl[] = {
-	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
-	{ 0, }
-};
+/*
+ * We have to call pci_eisa_init_early() before pnpacpi_init()/isapnp_init().
+ *   Otherwise pnp resource will get enabled early and could prevent eisa
+ *   to be initialized.
+ * Also need to make sure pci_eisa_init_early() is called after
+ * x86/pci_subsys_init().
+ * So need to use subsys_initcall_sync with it.
+ */
+static int __init pci_eisa_init_early(void)
+{
+	struct pci_dev *dev = NULL;
+	int ret;
 
-static struct pci_driver __refdata pci_eisa_driver = {
-	.name		= "pci_eisa",
-	.id_table	= pci_eisa_pci_tbl,
-	.probe		= pci_eisa_init,
-};
+	for_each_pci_dev(dev)
+		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) {
+			ret = pci_eisa_init(dev);
+			if (ret)
+				return ret;
+		}
 
-static int __init pci_eisa_init_module (void)
-{
-	return pci_register_driver (&pci_eisa_driver);
+	return 0;
 }
-
-device_initcall(pci_eisa_init_module);
-MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl);
+subsys_initcall_sync(pci_eisa_init_early);
diff -druNp linux-libre-3.8-gnu1/drivers/firewire/core-device.c linux-libre-3.8.13-gnu1/drivers/firewire/core-device.c
--- linux-libre-3.8-gnu1/drivers/firewire/core-device.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/firewire/core-device.c	2013-05-11 16:57:46.000000000 -0400
@@ -1020,6 +1020,10 @@ static void fw_device_init(struct work_s
 	ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ?
 	      idr_get_new(&fw_device_idr, device, &minor) :
 	      -ENOMEM;
+	if (minor >= 1 << MINORBITS) {
+		idr_remove(&fw_device_idr, minor);
+		minor = -ENOSPC;
+	}
 	up_write(&fw_device_rwsem);
 
 	if (ret < 0)
diff -druNp linux-libre-3.8-gnu1/drivers/firmware/dmi_scan.c linux-libre-3.8.13-gnu1/drivers/firmware/dmi_scan.c
--- linux-libre-3.8-gnu1/drivers/firmware/dmi_scan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/firmware/dmi_scan.c	2013-05-11 16:57:46.000000000 -0400
@@ -442,7 +442,6 @@ static int __init dmi_present(const char
 static int __init smbios_present(const char __iomem *p)
 {
 	u8 buf[32];
-	int offset = 0;
 
 	memcpy_fromio(buf, p, 32);
 	if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
@@ -461,9 +460,9 @@ static int __init smbios_present(const c
 			dmi_ver = 0x0206;
 			break;
 		}
-		offset = 16;
+		return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
 	}
-	return dmi_present(buf + offset);
+	return 1;
 }
 
 void __init dmi_scan_machine(void)
diff -druNp linux-libre-3.8-gnu1/drivers/firmware/efivars.c linux-libre-3.8.13-gnu1/drivers/firmware/efivars.c
--- linux-libre-3.8-gnu1/drivers/firmware/efivars.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/firmware/efivars.c	2013-05-11 16:57:46.000000000 -0400
@@ -79,6 +79,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/pstore.h>
+#include <linux/ctype.h>
 
 #include <linux/fs.h>
 #include <linux/ramfs.h>
@@ -102,6 +103,11 @@ MODULE_VERSION(EFIVARS_VERSION);
  */
 #define GUID_LEN 36
 
+static bool efivars_pstore_disable =
+	IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
+
+module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
+
 /*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
@@ -405,10 +411,11 @@ static efi_status_t
 get_var_data(struct efivars *efivars, struct efi_variable *var)
 {
 	efi_status_t status;
+	unsigned long flags;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irqsave(&efivars->lock, flags);
 	status = get_var_data_locked(efivars, var);
-	spin_unlock(&efivars->lock);
+	spin_unlock_irqrestore(&efivars->lock, flags);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
@@ -417,6 +424,44 @@ get_var_data(struct efivars *efivars, st
 	return status;
 }
 
+static efi_status_t
+check_var_size_locked(struct efivars *efivars, u32 attributes,
+			unsigned long size)
+{
+	u64 storage_size, remaining_size, max_size;
+	efi_status_t status;
+	const struct efivar_operations *fops = efivars->ops;
+
+	if (!efivars->ops->query_variable_info)
+		return EFI_UNSUPPORTED;
+
+	status = fops->query_variable_info(attributes, &storage_size,
+					   &remaining_size, &max_size);
+
+	if (status != EFI_SUCCESS)
+		return status;
+
+	if (!storage_size || size > remaining_size || size > max_size ||
+	    (remaining_size - size) < (storage_size / 2))
+		return EFI_OUT_OF_RESOURCES;
+
+	return status;
+}
+
+
+static efi_status_t
+check_var_size(struct efivars *efivars, u32 attributes, unsigned long size)
+{
+	efi_status_t status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&efivars->lock, flags);
+	status = check_var_size_locked(efivars, attributes, size);
+	spin_unlock_irqrestore(&efivars->lock, flags);
+
+	return status;
+}
+
 static ssize_t
 efivar_guid_read(struct efivar_entry *entry, char *buf)
 {
@@ -537,14 +582,19 @@ efivar_store_raw(struct efivar_entry *en
 		return -EINVAL;
 	}
 
-	spin_lock(&efivars->lock);
-	status = efivars->ops->set_variable(new_var->VariableName,
-					    &new_var->VendorGuid,
-					    new_var->Attributes,
-					    new_var->DataSize,
-					    new_var->Data);
+	spin_lock_irq(&efivars->lock);
 
-	spin_unlock(&efivars->lock);
+	status = check_var_size_locked(efivars, new_var->Attributes,
+	       new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+
+	if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
+		status = efivars->ops->set_variable(new_var->VariableName,
+						    &new_var->VendorGuid,
+						    new_var->Attributes,
+						    new_var->DataSize,
+						    new_var->Data);
+
+	spin_unlock_irq(&efivars->lock);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -693,8 +743,7 @@ static ssize_t efivarfs_file_write(struc
 	u32 attributes;
 	struct inode *inode = file->f_mapping->host;
 	unsigned long datasize = count - sizeof(attributes);
-	unsigned long newdatasize;
-	u64 storage_size, remaining_size, max_size;
+	unsigned long newdatasize, varsize;
 	ssize_t bytes = 0;
 
 	if (count < sizeof(attributes))
@@ -713,28 +762,18 @@ static ssize_t efivarfs_file_write(struc
 	 * amounts of memory. Pick a default size of 64K if
 	 * QueryVariableInfo() isn't supported by the firmware.
 	 */
-	spin_lock(&efivars->lock);
-
-	if (!efivars->ops->query_variable_info)
-		status = EFI_UNSUPPORTED;
-	else {
-		const struct efivar_operations *fops = efivars->ops;
-		status = fops->query_variable_info(attributes, &storage_size,
-						   &remaining_size, &max_size);
-	}
 
-	spin_unlock(&efivars->lock);
+	varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
+	status = check_var_size(efivars, attributes, varsize);
 
 	if (status != EFI_SUCCESS) {
 		if (status != EFI_UNSUPPORTED)
 			return efi_status_to_err(status);
 
-		remaining_size = 65536;
+		if (datasize > 65536)
+			return -ENOSPC;
 	}
 
-	if (datasize > remaining_size)
-		return -ENOSPC;
-
 	data = kmalloc(datasize, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -754,7 +793,20 @@ static ssize_t efivarfs_file_write(struc
 	 * set_variable call, and removal of the variable from the efivars
 	 * list (in the case of an authenticated delete).
 	 */
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
+
+	/*
+	 * Ensure that the available space hasn't shrunk below the safe level
+	 */
+
+	status = check_var_size_locked(efivars, attributes, varsize);
+
+	if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
+		spin_unlock_irq(&efivars->lock);
+		kfree(data);
+
+		return efi_status_to_err(status);
+	}
 
 	status = efivars->ops->set_variable(var->var.VariableName,
 					    &var->var.VendorGuid,
@@ -762,7 +814,7 @@ static ssize_t efivarfs_file_write(struc
 					    data);
 
 	if (status != EFI_SUCCESS) {
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		kfree(data);
 
 		return efi_status_to_err(status);
@@ -783,21 +835,21 @@ static ssize_t efivarfs_file_write(struc
 					    NULL);
 
 	if (status == EFI_BUFFER_TOO_SMALL) {
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		mutex_lock(&inode->i_mutex);
 		i_size_write(inode, newdatasize + sizeof(attributes));
 		mutex_unlock(&inode->i_mutex);
 
 	} else if (status == EFI_NOT_FOUND) {
 		list_del(&var->list);
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		efivar_unregister(var);
 		drop_nlink(inode);
 		d_delete(file->f_dentry);
 		dput(file->f_dentry);
 
 	} else {
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		pr_warn("efivarfs: inconsistent EFI variable implementation? "
 				"status = %lx\n", status);
 	}
@@ -819,11 +871,11 @@ static ssize_t efivarfs_file_read(struct
 	void *data;
 	ssize_t size = 0;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 	status = efivars->ops->get_variable(var->var.VariableName,
 					    &var->var.VendorGuid,
 					    &attributes, &datasize, NULL);
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 
 	if (status != EFI_BUFFER_TOO_SMALL)
 		return efi_status_to_err(status);
@@ -833,12 +885,12 @@ static ssize_t efivarfs_file_read(struct
 	if (!data)
 		return -ENOMEM;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 	status = efivars->ops->get_variable(var->var.VariableName,
 					    &var->var.VendorGuid,
 					    &attributes, &datasize,
 					    (data + sizeof(attributes)));
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 
 	if (status != EFI_SUCCESS) {
 		size = efi_status_to_err(status);
@@ -900,6 +952,48 @@ static struct inode *efivarfs_get_inode(
 	return inode;
 }
 
+/*
+ * Return true if 'str' is a valid efivarfs filename of the form,
+ *
+ *	VariableName-12345678-1234-1234-1234-1234567891bc
+ */
+static bool efivarfs_valid_name(const char *str, int len)
+{
+	static const char dashes[GUID_LEN] = {
+		[8] = 1, [13] = 1, [18] = 1, [23] = 1
+	};
+	const char *s = str + len - GUID_LEN;
+	int i;
+
+	/*
+	 * We need a GUID, plus at least one letter for the variable name,
+	 * plus the '-' separator
+	 */
+	if (len < GUID_LEN + 2)
+		return false;
+
+	/* GUID must be preceded by a '-' */
+	if (*(s - 1) != '-')
+		return false;
+
+	/*
+	 * Validate that 's' is of the correct format, e.g.
+	 *
+	 *	12345678-1234-1234-1234-123456789abc
+	 */
+	for (i = 0; i < GUID_LEN; i++) {
+		if (dashes[i]) {
+			if (*s++ != '-')
+				return false;
+		} else {
+			if (!isxdigit(*s++))
+				return false;
+		}
+	}
+
+	return true;
+}
+
 static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
 {
 	guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
@@ -928,11 +1022,7 @@ static int efivarfs_create(struct inode
 	struct efivar_entry *var;
 	int namelen, i = 0, err = 0;
 
-	/*
-	 * We need a GUID, plus at least one letter for the variable name,
-	 * plus the '-' separator
-	 */
-	if (dentry->d_name.len < GUID_LEN + 2)
+	if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
 		return -EINVAL;
 
 	inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
@@ -966,9 +1056,9 @@ static int efivarfs_create(struct inode
 		goto out;
 
 	kobject_uevent(&var->kobj, KOBJ_ADD);
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 	list_add(&var->list, &efivars->list);
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 	d_instantiate(dentry, inode);
 	dget(dentry);
 out:
@@ -985,7 +1075,7 @@ static int efivarfs_unlink(struct inode
 	struct efivars *efivars = var->efivars;
 	efi_status_t status;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 
 	status = efivars->ops->set_variable(var->var.VariableName,
 					    &var->var.VendorGuid,
@@ -993,17 +1083,102 @@ static int efivarfs_unlink(struct inode
 
 	if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) {
 		list_del(&var->list);
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		efivar_unregister(var);
 		drop_nlink(dentry->d_inode);
 		dput(dentry);
 		return 0;
 	}
 
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 	return -EINVAL;
 };
 
+/*
+ * Compare two efivarfs file names.
+ *
+ * An efivarfs filename is composed of two parts,
+ *
+ *	1. A case-sensitive variable name
+ *	2. A case-insensitive GUID
+ *
+ * So we need to perform a case-sensitive match on part 1 and a
+ * case-insensitive match on part 2.
+ */
+static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
+			      const struct dentry *dentry, const struct inode *inode,
+			      unsigned int len, const char *str,
+			      const struct qstr *name)
+{
+	int guid = len - GUID_LEN;
+
+	if (name->len != len)
+		return 1;
+
+	/* Case-sensitive compare for the variable name */
+	if (memcmp(str, name->name, guid))
+		return 1;
+
+	/* Case-insensitive compare for the GUID */
+	return strncasecmp(name->name + guid, str + guid, GUID_LEN);
+}
+
+static int efivarfs_d_hash(const struct dentry *dentry,
+			   const struct inode *inode, struct qstr *qstr)
+{
+	unsigned long hash = init_name_hash();
+	const unsigned char *s = qstr->name;
+	unsigned int len = qstr->len;
+
+	if (!efivarfs_valid_name(s, len))
+		return -EINVAL;
+
+	while (len-- > GUID_LEN)
+		hash = partial_name_hash(*s++, hash);
+
+	/* GUID is case-insensitive. */
+	while (len--)
+		hash = partial_name_hash(tolower(*s++), hash);
+
+	qstr->hash = end_name_hash(hash);
+	return 0;
+}
+
+/*
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
+ */
+static int efivarfs_delete_dentry(const struct dentry *dentry)
+{
+	return 1;
+}
+
+static struct dentry_operations efivarfs_d_ops = {
+	.d_compare = efivarfs_d_compare,
+	.d_hash = efivarfs_d_hash,
+	.d_delete = efivarfs_delete_dentry,
+};
+
+static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
+{
+	struct dentry *d;
+	struct qstr q;
+	int err;
+
+	q.name = name;
+	q.len = strlen(name);
+
+	err = efivarfs_d_hash(NULL, NULL, &q);
+	if (err)
+		return ERR_PTR(err);
+
+	d = d_alloc(parent, &q);
+	if (d)
+		return d;
+
+	return ERR_PTR(-ENOMEM);
+}
+
 static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode = NULL;
@@ -1011,6 +1186,7 @@ static int efivarfs_fill_super(struct su
 	struct efivar_entry *entry, *n;
 	struct efivars *efivars = &__efivars;
 	char *name;
+	int err = -ENOMEM;
 
 	efivarfs_sb = sb;
 
@@ -1019,6 +1195,7 @@ static int efivarfs_fill_super(struct su
 	sb->s_blocksize_bits    = PAGE_CACHE_SHIFT;
 	sb->s_magic             = EFIVARFS_MAGIC;
 	sb->s_op                = &efivarfs_ops;
+	sb->s_d_op		= &efivarfs_d_ops;
 	sb->s_time_gran         = 1;
 
 	inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
@@ -1059,20 +1236,22 @@ static int efivarfs_fill_super(struct su
 		if (!inode)
 			goto fail_name;
 
-		dentry = d_alloc_name(root, name);
-		if (!dentry)
+		dentry = efivarfs_alloc_dentry(root, name);
+		if (IS_ERR(dentry)) {
+			err = PTR_ERR(dentry);
 			goto fail_inode;
+		}
 
 		/* copied by the above to local storage in the dentry. */
 		kfree(name);
 
-		spin_lock(&efivars->lock);
+		spin_lock_irq(&efivars->lock);
 		efivars->ops->get_variable(entry->var.VariableName,
 					   &entry->var.VendorGuid,
 					   &entry->var.Attributes,
 					   &size,
 					   NULL);
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 
 		mutex_lock(&inode->i_mutex);
 		inode->i_private = entry;
@@ -1088,7 +1267,7 @@ fail_inode:
 fail_name:
 	kfree(name);
 fail:
-	return -ENOMEM;
+	return err;
 }
 
 static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
@@ -1109,21 +1288,31 @@ static struct file_system_type efivarfs_
 	.kill_sb = efivarfs_kill_sb,
 };
 
+/*
+ * Handle negative dentry.
+ */
+static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry,
+				      unsigned int flags)
+{
+	if (dentry->d_name.len > NAME_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+	d_add(dentry, NULL);
+	return NULL;
+}
+
 static const struct inode_operations efivarfs_dir_inode_operations = {
-	.lookup = simple_lookup,
+	.lookup = efivarfs_lookup,
 	.unlink = efivarfs_unlink,
 	.create = efivarfs_create,
 };
 
-static struct pstore_info efi_pstore_info;
-
-#ifdef CONFIG_PSTORE
+#ifdef CONFIG_EFI_VARS_PSTORE
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
 	struct efivars *efivars = psi->data;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 	efivars->walk_entry = list_first_entry(&efivars->list,
 					       struct efivar_entry, list);
 	return 0;
@@ -1133,7 +1322,7 @@ static int efi_pstore_close(struct pstor
 {
 	struct efivars *efivars = psi->data;
 
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 	return 0;
 }
 
@@ -1207,22 +1396,22 @@ static int efi_pstore_write(enum pstore_
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
 	int i, ret = 0;
-	u64 storage_space, remaining_space, max_variable_size;
 	efi_status_t status = EFI_NOT_FOUND;
+	unsigned long flags;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irqsave(&efivars->lock, flags);
 
 	/*
 	 * Check if there is a space enough to log.
 	 * size: a size of logging data
 	 * DUMP_NAME_LEN * 2: a maximum size of variable name
 	 */
-	status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES,
-						   &storage_space,
-						   &remaining_space,
-						   &max_variable_size);
-	if (status || remaining_space < size + DUMP_NAME_LEN * 2) {
-		spin_unlock(&efivars->lock);
+
+	status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES,
+					 size + DUMP_NAME_LEN * 2);
+
+	if (status) {
+		spin_unlock_irqrestore(&efivars->lock, flags);
 		*id = part;
 		return -ENOSPC;
 	}
@@ -1236,7 +1425,7 @@ static int efi_pstore_write(enum pstore_
 	efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
 				   size, psi->buf);
 
-	spin_unlock(&efivars->lock);
+	spin_unlock_irqrestore(&efivars->lock, flags);
 
 	if (size)
 		ret = efivar_create_sysfs_entry(efivars,
@@ -1263,7 +1452,7 @@ static int efi_pstore_erase(enum pstore_
 	sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
 		time.tv_sec);
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 
 	for (i = 0; i < DUMP_NAME_LEN; i++)
 		efi_name[i] = name[i];
@@ -1307,45 +1496,13 @@ static int efi_pstore_erase(enum pstore_
 	if (found)
 		list_del(&found->list);
 
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 
 	if (found)
 		efivar_unregister(found);
 
 	return 0;
 }
-#else
-static int efi_pstore_open(struct pstore_info *psi)
-{
-	return 0;
-}
-
-static int efi_pstore_close(struct pstore_info *psi)
-{
-	return 0;
-}
-
-static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count,
-			       struct timespec *timespec,
-			       char **buf, struct pstore_info *psi)
-{
-	return -1;
-}
-
-static int efi_pstore_write(enum pstore_type_id type,
-		enum kmsg_dump_reason reason, u64 *id,
-		unsigned int part, int count, size_t size,
-		struct pstore_info *psi)
-{
-	return 0;
-}
-
-static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
-			    struct timespec time, struct pstore_info *psi)
-{
-	return 0;
-}
-#endif
 
 static struct pstore_info efi_pstore_info = {
 	.owner		= THIS_MODULE,
@@ -1357,6 +1514,24 @@ static struct pstore_info efi_pstore_inf
 	.erase		= efi_pstore_erase,
 };
 
+static void efivar_pstore_register(struct efivars *efivars)
+{
+	efivars->efi_pstore_info = efi_pstore_info;
+	efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
+	if (efivars->efi_pstore_info.buf) {
+		efivars->efi_pstore_info.bufsize = 1024;
+		efivars->efi_pstore_info.data = efivars;
+		spin_lock_init(&efivars->efi_pstore_info.buf_lock);
+		pstore_register(&efivars->efi_pstore_info);
+	}
+}
+#else
+static void efivar_pstore_register(struct efivars *efivars)
+{
+	return;
+}
+#endif
+
 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 			     struct bin_attribute *bin_attr,
 			     char *buf, loff_t pos, size_t count)
@@ -1377,7 +1552,7 @@ static ssize_t efivar_create(struct file
 		return -EINVAL;
 	}
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 
 	/*
 	 * Does this variable already exist?
@@ -1395,10 +1570,18 @@ static ssize_t efivar_create(struct file
 		}
 	}
 	if (found) {
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		return -EINVAL;
 	}
 
+	status = check_var_size_locked(efivars, new_var->Attributes,
+	       new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+
+	if (status && status != EFI_UNSUPPORTED) {
+		spin_unlock_irq(&efivars->lock);
+		return efi_status_to_err(status);
+	}
+
 	/* now *really* create the variable via EFI */
 	status = efivars->ops->set_variable(new_var->VariableName,
 					    &new_var->VendorGuid,
@@ -1409,10 +1592,10 @@ static ssize_t efivar_create(struct file
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 			status);
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		return -EIO;
 	}
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 
 	/* Create the entry in sysfs.  Locking is not required here */
 	status = efivar_create_sysfs_entry(efivars,
@@ -1440,7 +1623,7 @@ static ssize_t efivar_delete(struct file
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 
 	/*
 	 * Does this variable already exist?
@@ -1458,7 +1641,7 @@ static ssize_t efivar_delete(struct file
 		}
 	}
 	if (!found) {
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		return -EINVAL;
 	}
 	/* force the Attributes/DataSize to 0 to ensure deletion */
@@ -1474,18 +1657,65 @@ static ssize_t efivar_delete(struct file
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 			status);
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		return -EIO;
 	}
 	list_del(&search_efivar->list);
 	/* We need to release this lock before unregistering. */
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 	efivar_unregister(search_efivar);
 
 	/* It's dead Jim.... */
 	return count;
 }
 
+static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
+{
+	struct efivar_entry *entry, *n;
+	struct efivars *efivars = &__efivars;
+	unsigned long strsize1, strsize2;
+	bool found = false;
+
+	strsize1 = utf16_strsize(variable_name, 1024);
+	list_for_each_entry_safe(entry, n, &efivars->list, list) {
+		strsize2 = utf16_strsize(entry->var.VariableName, 1024);
+		if (strsize1 == strsize2 &&
+			!memcmp(variable_name, &(entry->var.VariableName),
+				strsize2) &&
+			!efi_guidcmp(entry->var.VendorGuid,
+				*vendor)) {
+			found = true;
+			break;
+		}
+	}
+	return found;
+}
+
+/*
+ * Returns the size of variable_name, in bytes, including the
+ * terminating NULL character, or variable_name_size if no NULL
+ * character is found among the first variable_name_size bytes.
+ */
+static unsigned long var_name_strnsize(efi_char16_t *variable_name,
+				       unsigned long variable_name_size)
+{
+	unsigned long len;
+	efi_char16_t c;
+
+	/*
+	 * The variable name is, by definition, a NULL-terminated
+	 * string, so make absolutely sure that variable_name_size is
+	 * the value we expect it to be. If not, return the real size.
+	 */
+	for (len = 2; len <= variable_name_size; len += sizeof(c)) {
+		c = variable_name[(len / sizeof(c)) - 1];
+		if (!c)
+			break;
+	}
+
+	return min(len, variable_name_size);
+}
+
 /*
  * Let's not leave out systab information that snuck into
  * the efivars driver
@@ -1594,9 +1824,9 @@ efivar_create_sysfs_entry(struct efivars
 	kfree(short_name);
 	short_name = NULL;
 
-	spin_lock(&efivars->lock);
+	spin_lock_irq(&efivars->lock);
 	list_add(&new_efivar->list, &efivars->list);
-	spin_unlock(&efivars->lock);
+	spin_unlock_irq(&efivars->lock);
 
 	return 0;
 }
@@ -1665,9 +1895,9 @@ void unregister_efivars(struct efivars *
 	struct efivar_entry *entry, *n;
 
 	list_for_each_entry_safe(entry, n, &efivars->list, list) {
-		spin_lock(&efivars->lock);
+		spin_lock_irq(&efivars->lock);
 		list_del(&entry->list);
-		spin_unlock(&efivars->lock);
+		spin_unlock_irq(&efivars->lock);
 		efivar_unregister(entry);
 	}
 	if (efivars->new_var)
@@ -1681,6 +1911,28 @@ void unregister_efivars(struct efivars *
 }
 EXPORT_SYMBOL_GPL(unregister_efivars);
 
+/*
+ * Print a warning when duplicate EFI variables are encountered and
+ * disable the sysfs workqueue since the firmware is buggy.
+ */
+static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
+			     unsigned long len16)
+{
+	size_t i, len8 = len16 / sizeof(efi_char16_t);
+	char *s8;
+
+	s8 = kzalloc(len8, GFP_KERNEL);
+	if (!s8)
+		return;
+
+	for (i = 0; i < len8; i++)
+		s8[i] = s16[i];
+
+	printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
+	       s8, vendor_guid);
+	kfree(s8);
+}
+
 int register_efivars(struct efivars *efivars,
 		     const struct efivar_operations *ops,
 		     struct kobject *parent_kobj)
@@ -1729,6 +1981,24 @@ int register_efivars(struct efivars *efi
 						&vendor_guid);
 		switch (status) {
 		case EFI_SUCCESS:
+			variable_name_size = var_name_strnsize(variable_name,
+							       variable_name_size);
+
+			/*
+			 * Some firmware implementations return the
+			 * same variable name on multiple calls to
+			 * get_next_variable(). Terminate the loop
+			 * immediately as there is no guarantee that
+			 * we'll ever see a different variable name,
+			 * and may end up looping here forever.
+			 */
+			if (variable_is_present(variable_name, &vendor_guid)) {
+				dup_variable_bug(variable_name, &vendor_guid,
+						 variable_name_size);
+				status = EFI_NOT_FOUND;
+				break;
+			}
+
 			efivar_create_sysfs_entry(efivars,
 						  variable_name_size,
 						  variable_name,
@@ -1748,15 +2018,8 @@ int register_efivars(struct efivars *efi
 	if (error)
 		unregister_efivars(efivars);
 
-	efivars->efi_pstore_info = efi_pstore_info;
-
-	efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
-	if (efivars->efi_pstore_info.buf) {
-		efivars->efi_pstore_info.bufsize = 1024;
-		efivars->efi_pstore_info.data = efivars;
-		spin_lock_init(&efivars->efi_pstore_info.buf_lock);
-		pstore_register(&efivars->efi_pstore_info);
-	}
+	if (!efivars_pstore_disable)
+		efivar_pstore_register(efivars);
 
 	register_filesystem(&efivarfs_type);
 
diff -druNp linux-libre-3.8-gnu1/drivers/firmware/Kconfig linux-libre-3.8.13-gnu1/drivers/firmware/Kconfig
--- linux-libre-3.8-gnu1/drivers/firmware/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/firmware/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -53,6 +53,24 @@ config EFI_VARS
 	  Subsequent efibootmgr releases may be found at:
 	  <http://linux.dell.com/efibootmgr>
 
+config EFI_VARS_PSTORE
+	bool "Register efivars backend for pstore"
+	depends on EFI_VARS && PSTORE
+	default y
+	help
+	  Say Y here to enable use efivars as a backend to pstore. This
+	  will allow writing console messages, crash dumps, or anything
+	  else supported by pstore to EFI variables.
+
+config EFI_VARS_PSTORE_DEFAULT_DISABLE
+	bool "Disable using efivars as a pstore backend by default"
+	depends on EFI_VARS_PSTORE
+	default n
+	help
+	  Saying Y here will disable the use of efivars as a storage
+	  backend for pstore by default. This setting can be overridden
+	  using the efivars module's pstore_disable parameter.
+
 config EFI_PCDP
 	bool "Console device selection via EFI PCDP or HCDP table"
 	depends on ACPI && EFI && IA64
diff -druNp linux-libre-3.8-gnu1/drivers/gpio/gpio-em.c linux-libre-3.8.13-gnu1/drivers/gpio/gpio-em.c
--- linux-libre-3.8-gnu1/drivers/gpio/gpio-em.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpio/gpio-em.c	2013-05-11 16:57:46.000000000 -0400
@@ -299,8 +299,9 @@ static int em_gio_probe(struct platform_
 	irq_chip->irq_set_type = em_gio_irq_set_type;
 	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE;
 
-	p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
 					      pdata->number_of_pins,
+					      pdata->irq_base,
 					      &em_gio_irq_domain_ops, p);
 	if (!p->irq_domain) {
 		ret = -ENXIO;
diff -druNp linux-libre-3.8-gnu1/drivers/gpio/gpiolib-of.c linux-libre-3.8.13-gnu1/drivers/gpio/gpiolib-of.c
--- linux-libre-3.8-gnu1/drivers/gpio/gpiolib-of.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpio/gpiolib-of.c	2013-05-11 16:57:46.000000000 -0400
@@ -228,7 +228,7 @@ static void of_gpiochip_add_pin_range(st
 	if (!np)
 		return;
 
-	do {
+	for (;; index++) {
 		ret = of_parse_phandle_with_args(np, "gpio-ranges",
 				"#gpio-range-cells", index, &pinspec);
 		if (ret)
@@ -257,8 +257,7 @@ static void of_gpiochip_add_pin_range(st
 
 		if (ret)
 			break;
-
-	} while (index++);
+	}
 }
 
 #else
diff -druNp linux-libre-3.8-gnu1/drivers/gpio/gpio-mvebu.c linux-libre-3.8.13-gnu1/drivers/gpio/gpio-mvebu.c
--- linux-libre-3.8-gnu1/drivers/gpio/gpio-mvebu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpio/gpio-mvebu.c	2013-05-11 16:57:46.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/io.h>
 #include <linux/of_irq.h>
 #include <linux/of_device.h>
+#include <linux/clk.h>
 #include <linux/pinctrl/consumer.h>
 
 /*
@@ -495,6 +496,7 @@ static int mvebu_gpio_probe(struct platf
 	struct resource *res;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	struct clk *clk;
 	unsigned int ngpios;
 	int soc_variant;
 	int i, cpu, id;
@@ -528,6 +530,11 @@ static int mvebu_gpio_probe(struct platf
 		return id;
 	}
 
+	clk = devm_clk_get(&pdev->dev, NULL);
+	/* Not all SoCs require a clock.*/
+	if (!IS_ERR(clk))
+		clk_prepare_enable(clk);
+
 	mvchip->soc_variant = soc_variant;
 	mvchip->chip.label = dev_name(&pdev->dev);
 	mvchip->chip.dev = &pdev->dev;
diff -druNp linux-libre-3.8-gnu1/drivers/gpio/gpio-stmpe.c linux-libre-3.8.13-gnu1/drivers/gpio/gpio-stmpe.c
--- linux-libre-3.8-gnu1/drivers/gpio/gpio-stmpe.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpio/gpio-stmpe.c	2013-05-11 16:57:46.000000000 -0400
@@ -307,11 +307,15 @@ static const struct irq_domain_ops stmpe
 	.xlate = irq_domain_xlate_twocell,
 };
 
-static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
+		struct device_node *np)
 {
-	int base = stmpe_gpio->irq_base;
+	int base = 0;
 
-	stmpe_gpio->domain = irq_domain_add_simple(NULL,
+	if (!np)
+		base = stmpe_gpio->irq_base;
+
+	stmpe_gpio->domain = irq_domain_add_simple(np,
 				stmpe_gpio->chip.ngpio, base,
 				&stmpe_gpio_irq_simple_ops, stmpe_gpio);
 	if (!stmpe_gpio->domain) {
@@ -346,6 +350,9 @@ static int stmpe_gpio_probe(struct platf
 	stmpe_gpio->chip = template_chip;
 	stmpe_gpio->chip.ngpio = stmpe->num_gpios;
 	stmpe_gpio->chip.dev = &pdev->dev;
+#ifdef CONFIG_OF
+	stmpe_gpio->chip.of_node = np;
+#endif
 	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
 	if (pdata)
@@ -366,7 +373,7 @@ static int stmpe_gpio_probe(struct platf
 		goto out_free;
 
 	if (irq >= 0) {
-		ret = stmpe_gpio_irq_init(stmpe_gpio);
+		ret = stmpe_gpio_irq_init(stmpe_gpio, np);
 		if (ret)
 			goto out_disable;
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/ast/ast_drv.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/ast/ast_drv.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/ast/ast_drv.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/ast/ast_drv.h	2013-05-11 16:57:46.000000000 -0400
@@ -239,6 +239,8 @@ struct ast_fbdev {
 	void *sysram;
 	int size;
 	struct ttm_bo_kmap_obj mapping;
+	int x1, y1, x2, y2; /* dirty rect */
+	spinlock_t dirty_lock;
 };
 
 #define to_ast_crtc(x) container_of(x, struct ast_crtc, base)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/ast/ast_fb.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/ast/ast_fb.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/ast/ast_fb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/ast/ast_fb.c	2013-05-11 16:57:46.000000000 -0400
@@ -52,16 +52,52 @@ static void ast_dirty_update(struct ast_
 	int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8;
 	int ret;
 	bool unmap = false;
+	bool store_for_later = false;
+	int x2, y2;
+	unsigned long flags;
 
 	obj = afbdev->afb.obj;
 	bo = gem_to_ast_bo(obj);
 
+	/*
+	 * try and reserve the BO, if we fail with busy
+	 * then the BO is being moved and we should
+	 * store up the damage until later.
+	 */
 	ret = ast_bo_reserve(bo, true);
 	if (ret) {
-		DRM_ERROR("failed to reserve fb bo\n");
+		if (ret != -EBUSY)
+			return;
+
+		store_for_later = true;
+	}
+
+	x2 = x + width - 1;
+	y2 = y + height - 1;
+	spin_lock_irqsave(&afbdev->dirty_lock, flags);
+
+	if (afbdev->y1 < y)
+		y = afbdev->y1;
+	if (afbdev->y2 > y2)
+		y2 = afbdev->y2;
+	if (afbdev->x1 < x)
+		x = afbdev->x1;
+	if (afbdev->x2 > x2)
+		x2 = afbdev->x2;
+
+	if (store_for_later) {
+		afbdev->x1 = x;
+		afbdev->x2 = x2;
+		afbdev->y1 = y;
+		afbdev->y2 = y2;
+		spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
 		return;
 	}
 
+	afbdev->x1 = afbdev->y1 = INT_MAX;
+	afbdev->x2 = afbdev->y2 = 0;
+	spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
+
 	if (!bo->kmap.virtual) {
 		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
 		if (ret) {
@@ -71,10 +107,10 @@ static void ast_dirty_update(struct ast_
 		}
 		unmap = true;
 	}
-	for (i = y; i < y + height; i++) {
+	for (i = y; i <= y2; i++) {
 		/* assume equal stride for now */
 		src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp);
-		memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp);
+		memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp);
 
 	}
 	if (unmap)
@@ -305,6 +341,7 @@ int ast_fbdev_init(struct drm_device *de
 
 	ast->fbdev = afbdev;
 	afbdev->helper.funcs = &ast_fb_helper_funcs;
+	spin_lock_init(&afbdev->dirty_lock);
 	ret = drm_fb_helper_init(dev, &afbdev->helper,
 				 1, 1);
 	if (ret) {
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/ast/ast_ttm.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/ast/ast_ttm.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/ast/ast_ttm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/ast/ast_ttm.c	2013-05-11 16:57:46.000000000 -0400
@@ -316,7 +316,7 @@ int ast_bo_reserve(struct ast_bo *bo, bo
 
 	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
 	if (ret) {
-		if (ret != -ERESTARTSYS)
+		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
 		return ret;
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/cirrus/cirrus_drv.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/cirrus/cirrus_drv.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/cirrus/cirrus_drv.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/cirrus/cirrus_drv.h	2013-05-11 16:57:46.000000000 -0400
@@ -154,6 +154,8 @@ struct cirrus_fbdev {
 	struct list_head fbdev_list;
 	void *sysram;
 	int size;
+	int x1, y1, x2, y2; /* dirty rect */
+	spinlock_t dirty_lock;
 };
 
 struct cirrus_bo {
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/cirrus/cirrus_fbdev.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/cirrus/cirrus_fbdev.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/cirrus/cirrus_fbdev.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/cirrus/cirrus_fbdev.c	2013-05-11 16:57:46.000000000 -0400
@@ -26,16 +26,51 @@ static void cirrus_dirty_update(struct c
 	int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8;
 	int ret;
 	bool unmap = false;
+	bool store_for_later = false;
+	int x2, y2;
+	unsigned long flags;
 
 	obj = afbdev->gfb.obj;
 	bo = gem_to_cirrus_bo(obj);
 
+	/*
+	 * try and reserve the BO, if we fail with busy
+	 * then the BO is being moved and we should
+	 * store up the damage until later.
+	 */
 	ret = cirrus_bo_reserve(bo, true);
 	if (ret) {
-		DRM_ERROR("failed to reserve fb bo\n");
+		if (ret != -EBUSY)
+			return;
+		store_for_later = true;
+	}
+
+	x2 = x + width - 1;
+	y2 = y + height - 1;
+	spin_lock_irqsave(&afbdev->dirty_lock, flags);
+
+	if (afbdev->y1 < y)
+		y = afbdev->y1;
+	if (afbdev->y2 > y2)
+		y2 = afbdev->y2;
+	if (afbdev->x1 < x)
+		x = afbdev->x1;
+	if (afbdev->x2 > x2)
+		x2 = afbdev->x2;
+
+	if (store_for_later) {
+		afbdev->x1 = x;
+		afbdev->x2 = x2;
+		afbdev->y1 = y;
+		afbdev->y2 = y2;
+		spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
 		return;
 	}
 
+	afbdev->x1 = afbdev->y1 = INT_MAX;
+	afbdev->x2 = afbdev->y2 = 0;
+	spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
+
 	if (!bo->kmap.virtual) {
 		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
 		if (ret) {
@@ -282,6 +317,7 @@ int cirrus_fbdev_init(struct cirrus_devi
 
 	cdev->mode_info.gfbdev = gfbdev;
 	gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
+	spin_lock_init(&gfbdev->dirty_lock);
 
 	ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
 				 cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/cirrus/cirrus_ttm.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/cirrus/cirrus_ttm.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/cirrus/cirrus_ttm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/cirrus/cirrus_ttm.c	2013-05-11 16:57:46.000000000 -0400
@@ -321,7 +321,7 @@ int cirrus_bo_reserve(struct cirrus_bo *
 
 	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
 	if (ret) {
-		if (ret != -ERESTARTSYS)
+		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
 		return ret;
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/drm_crtc.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_crtc.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/drm_crtc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_crtc.c	2013-05-11 16:57:46.000000000 -0400
@@ -2089,7 +2089,7 @@ uint32_t drm_mode_legacy_fb_format(uint3
 
 	switch (bpp) {
 	case 8:
-		fmt = DRM_FORMAT_RGB332;
+		fmt = DRM_FORMAT_C8;
 		break;
 	case 16:
 		if (depth == 15)
@@ -3702,6 +3702,7 @@ void drm_fb_get_bpp_depth(uint32_t forma
 			  int *bpp)
 {
 	switch (format) {
+	case DRM_FORMAT_C8:
 	case DRM_FORMAT_RGB332:
 	case DRM_FORMAT_BGR233:
 		*depth = 8;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/drm_edid.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_edid.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/drm_edid.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_edid.c	2013-05-11 16:57:46.000000000 -0400
@@ -87,9 +87,6 @@ static struct edid_quirk {
 	int product_id;
 	u32 quirks;
 } edid_quirk_list[] = {
-	/* ASUS VW222S */
-	{ "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING },
-
 	/* Acer AL1706 */
 	{ "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
 	/* Acer F51 */
@@ -357,10 +354,14 @@ drm_do_get_edid(struct drm_connector *co
 				break;
 			}
 		}
-		if (i == 4)
+
+		if (i == 4 && print_bad_edid) {
 			dev_warn(connector->dev->dev,
 			 "%s: Ignoring invalid EDID block %d.\n",
 			 drm_get_connector_name(connector), j);
+
+			connector->bad_edid_counter++;
+		}
 	}
 
 	if (valid_extensions != block[0x7e]) {
@@ -893,7 +894,7 @@ static struct drm_display_mode *drm_mode
 	unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
 	unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
 	unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
-	unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+	unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4;
 	unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
 
 	/* ignore tiny modes */
@@ -974,6 +975,7 @@ set_size:
 	}
 
 	mode->type = DRM_MODE_TYPE_DRIVER;
+	mode->vrefresh = drm_mode_vrefresh(mode);
 	drm_mode_set_name(mode);
 
 	return mode;
@@ -2020,7 +2022,8 @@ int drm_add_edid_modes(struct drm_connec
 	num_modes += add_cvt_modes(connector, edid);
 	num_modes += add_standard_modes(connector, edid);
 	num_modes += add_established_modes(connector, edid);
-	num_modes += add_inferred_modes(connector, edid);
+	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
+		num_modes += add_inferred_modes(connector, edid);
 	num_modes += add_cea_modes(connector, edid);
 
 	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/drm_fops.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_fops.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/drm_fops.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_fops.c	2013-05-11 16:57:46.000000000 -0400
@@ -123,6 +123,7 @@ int drm_open(struct inode *inode, struct
 	int retcode = 0;
 	int need_setup = 0;
 	struct address_space *old_mapping;
+	struct address_space *old_imapping;
 
 	minor = idr_find(&drm_minors_idr, minor_id);
 	if (!minor)
@@ -137,6 +138,7 @@ int drm_open(struct inode *inode, struct
 	if (!dev->open_count++)
 		need_setup = 1;
 	mutex_lock(&dev->struct_mutex);
+	old_imapping = inode->i_mapping;
 	old_mapping = dev->dev_mapping;
 	if (old_mapping == NULL)
 		dev->dev_mapping = &inode->i_data;
@@ -159,8 +161,8 @@ int drm_open(struct inode *inode, struct
 
 err_undo:
 	mutex_lock(&dev->struct_mutex);
-	filp->f_mapping = old_mapping;
-	inode->i_mapping = old_mapping;
+	filp->f_mapping = old_imapping;
+	inode->i_mapping = old_imapping;
 	iput(container_of(dev->dev_mapping, struct inode, i_data));
 	dev->dev_mapping = old_mapping;
 	mutex_unlock(&dev->struct_mutex);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/drm_gem.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_gem.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/drm_gem.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_gem.c	2013-05-11 16:57:46.000000000 -0400
@@ -205,11 +205,11 @@ static void
 drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
 {
 	if (obj->import_attach) {
-		drm_prime_remove_imported_buf_handle(&filp->prime,
+		drm_prime_remove_buf_handle(&filp->prime,
 				obj->import_attach->dmabuf);
 	}
 	if (obj->export_dma_buf) {
-		drm_prime_remove_imported_buf_handle(&filp->prime,
+		drm_prime_remove_buf_handle(&filp->prime,
 				obj->export_dma_buf);
 	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/drm_prime.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_prime.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/drm_prime.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_prime.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,6 +61,7 @@ struct drm_prime_member {
 	struct dma_buf *dma_buf;
 	uint32_t handle;
 };
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
 
 int drm_gem_prime_handle_to_fd(struct drm_device *dev,
 		struct drm_file *file_priv, uint32_t handle, uint32_t flags,
@@ -68,7 +69,8 @@ int drm_gem_prime_handle_to_fd(struct dr
 {
 	struct drm_gem_object *obj;
 	void *buf;
-	int ret;
+	int ret = 0;
+	struct dma_buf *dmabuf;
 
 	obj = drm_gem_object_lookup(dev, file_priv, handle);
 	if (!obj)
@@ -77,43 +79,44 @@ int drm_gem_prime_handle_to_fd(struct dr
 	mutex_lock(&file_priv->prime.lock);
 	/* re-export the original imported object */
 	if (obj->import_attach) {
-		get_dma_buf(obj->import_attach->dmabuf);
-		*prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags);
-		drm_gem_object_unreference_unlocked(obj);
-		mutex_unlock(&file_priv->prime.lock);
-		return 0;
+		dmabuf = obj->import_attach->dmabuf;
+		goto out_have_obj;
 	}
 
 	if (obj->export_dma_buf) {
-		get_dma_buf(obj->export_dma_buf);
-		*prime_fd = dma_buf_fd(obj->export_dma_buf, flags);
-		drm_gem_object_unreference_unlocked(obj);
-	} else {
-		buf = dev->driver->gem_prime_export(dev, obj, flags);
-		if (IS_ERR(buf)) {
-			/* normally the created dma-buf takes ownership of the ref,
-			 * but if that fails then drop the ref
-			 */
-			drm_gem_object_unreference_unlocked(obj);
-			mutex_unlock(&file_priv->prime.lock);
-			return PTR_ERR(buf);
-		}
-		obj->export_dma_buf = buf;
-		*prime_fd = dma_buf_fd(buf, flags);
+		dmabuf = obj->export_dma_buf;
+		goto out_have_obj;
 	}
+
+	buf = dev->driver->gem_prime_export(dev, obj, flags);
+	if (IS_ERR(buf)) {
+		/* normally the created dma-buf takes ownership of the ref,
+		 * but if that fails then drop the ref
+		 */
+		ret = PTR_ERR(buf);
+		goto out;
+	}
+	obj->export_dma_buf = buf;
+
 	/* if we've exported this buffer the cheat and add it to the import list
 	 * so we get the correct handle back
 	 */
-	ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
-			obj->export_dma_buf, handle);
-	if (ret) {
-		drm_gem_object_unreference_unlocked(obj);
-		mutex_unlock(&file_priv->prime.lock);
-		return ret;
-	}
+	ret = drm_prime_add_buf_handle(&file_priv->prime,
+				       obj->export_dma_buf, handle);
+	if (ret)
+		goto out;
 
+	*prime_fd = dma_buf_fd(buf, flags);
 	mutex_unlock(&file_priv->prime.lock);
 	return 0;
+
+out_have_obj:
+	get_dma_buf(dmabuf);
+	*prime_fd = dma_buf_fd(dmabuf, flags);
+out:
+	drm_gem_object_unreference_unlocked(obj);
+	mutex_unlock(&file_priv->prime.lock);
+	return ret;
 }
 EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
 
@@ -130,7 +133,7 @@ int drm_gem_prime_fd_to_handle(struct dr
 
 	mutex_lock(&file_priv->prime.lock);
 
-	ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime,
+	ret = drm_prime_lookup_buf_handle(&file_priv->prime,
 			dma_buf, handle);
 	if (!ret) {
 		ret = 0;
@@ -149,7 +152,7 @@ int drm_gem_prime_fd_to_handle(struct dr
 	if (ret)
 		goto out_put;
 
-	ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
+	ret = drm_prime_add_buf_handle(&file_priv->prime,
 			dma_buf, *handle);
 	if (ret)
 		goto fail;
@@ -307,7 +310,7 @@ void drm_prime_destroy_file_private(stru
 }
 EXPORT_SYMBOL(drm_prime_destroy_file_private);
 
-int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
 {
 	struct drm_prime_member *member;
 
@@ -315,14 +318,14 @@ int drm_prime_add_imported_buf_handle(st
 	if (!member)
 		return -ENOMEM;
 
+	get_dma_buf(dma_buf);
 	member->dma_buf = dma_buf;
 	member->handle = handle;
 	list_add(&member->entry, &prime_fpriv->head);
 	return 0;
 }
-EXPORT_SYMBOL(drm_prime_add_imported_buf_handle);
 
-int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
+int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
 {
 	struct drm_prime_member *member;
 
@@ -334,19 +337,20 @@ int drm_prime_lookup_imported_buf_handle
 	}
 	return -ENOENT;
 }
-EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle);
+EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
 
-void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
 {
 	struct drm_prime_member *member, *safe;
 
 	mutex_lock(&prime_fpriv->lock);
 	list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
 		if (member->dma_buf == dma_buf) {
+			dma_buf_put(dma_buf);
 			list_del(&member->entry);
 			kfree(member);
 		}
 	}
 	mutex_unlock(&prime_fpriv->lock);
 }
-EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle);
+EXPORT_SYMBOL(drm_prime_remove_buf_handle);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/drm_usb.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_usb.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/drm_usb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/drm_usb.c	2013-05-11 16:57:46.000000000 -0400
@@ -18,7 +18,7 @@ int drm_get_usb_dev(struct usb_interface
 
 	usbdev = interface_to_usbdev(interface);
 	dev->usbdev = usbdev;
-	dev->dev = &usbdev->dev;
+	dev->dev = &interface->dev;
 
 	mutex_lock(&drm_global_mutex);
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/gma500/psb_irq.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/gma500/psb_irq.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/gma500/psb_irq.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/gma500/psb_irq.c	2013-05-11 16:57:46.000000000 -0400
@@ -211,7 +211,7 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS
 
 	vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
 
-	if (vdc_stat & _PSB_PIPE_EVENT_FLAG)
+	if (vdc_stat & (_PSB_PIPE_EVENT_FLAG|_PSB_IRQ_ASLE))
 		dsp_int = 1;
 
 	/* FIXME: Handle Medfield
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_debugfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_debugfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -103,7 +103,7 @@ static const char *cache_level_str(int t
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
-	seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s",
+	seq_printf(m, "%pK: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s",
 		   &obj->base,
 		   get_pin_flag(obj),
 		   get_tiling_flag(obj),
@@ -691,7 +691,7 @@ static int i915_error_state(struct seq_f
 
 	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
 		   error->time.tv_usec);
-	seq_printf(m, "Kernel: " UTS_RELEASE);
+	seq_printf(m, "Kernel: " UTS_RELEASE "\n");
 	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
 	seq_printf(m, "EIR: 0x%08x\n", error->eir);
 	seq_printf(m, "IER: 0x%08x\n", error->ier);
@@ -888,7 +888,7 @@ static int i915_cur_delayinfo(struct seq
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		u32 rpstat;
+		u32 rpstat, cagf;
 		u32 rpupei, rpcurup, rpprevup;
 		u32 rpdownei, rpcurdown, rpprevdown;
 		int max_freq;
@@ -907,6 +907,11 @@ static int i915_cur_delayinfo(struct seq
 		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
 		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
 		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
+		if (IS_HASWELL(dev))
+			cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
+		else
+			cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
+		cagf *= GT_FREQUENCY_MULTIPLIER;
 
 		gen6_gt_force_wake_put(dev_priv);
 		mutex_unlock(&dev->struct_mutex);
@@ -919,8 +924,7 @@ static int i915_cur_delayinfo(struct seq
 			   gt_perf_status & 0xff);
 		seq_printf(m, "Render p-state limit: %d\n",
 			   rp_state_limits & 0xff);
-		seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >>
-						GEN6_CAGF_SHIFT) * GT_FREQUENCY_MULTIPLIER);
+		seq_printf(m, "CAGF: %dMHz\n", cagf);
 		seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
 			   GEN6_CURICONT_MASK);
 		seq_printf(m, "RP CUR UP: %dus\n", rpcurup &
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_drv.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_drv.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_drv.c	2013-05-11 16:57:46.000000000 -0400
@@ -377,15 +377,15 @@ static const struct pci_device_id pciidl
 	INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
 	INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
 	INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
-	INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */
+	INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
+	INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
 	INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
-	INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */
-	INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */
+	INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
+	INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
 	INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
-	INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */
-	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */
+	INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
+	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
 	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
-	INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */
 	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
 	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
 	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_drv.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_drv.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_drv.h	2013-05-11 16:57:46.000000000 -0400
@@ -711,6 +711,7 @@ typedef struct drm_i915_private {
 	unsigned int int_crt_support:1;
 	unsigned int lvds_use_ssc:1;
 	unsigned int display_clock_mode:1;
+	unsigned int fdi_rx_polarity_inverted:1;
 	int lvds_ssc_freq;
 	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
 	unsigned int lvds_val; /* used for checking LVDS channel mode */
@@ -774,6 +775,7 @@ typedef struct drm_i915_private {
 		unsigned long gtt_start;
 		unsigned long gtt_mappable_end;
 		unsigned long gtt_end;
+		unsigned long stolen_base; /* limited to low memory (32-bit) */
 
 		struct io_mapping *gtt_mapping;
 		phys_addr_t gtt_base_addr;
@@ -919,7 +921,7 @@ typedef struct drm_i915_private {
 	bool hw_contexts_disabled;
 	uint32_t hw_context_size;
 
-	bool fdi_rx_polarity_reversed;
+	u32 fdi_rx_config;
 
 	struct i915_suspend_saved_registers regfile;
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem.c	2013-05-11 16:57:46.000000000 -0400
@@ -1918,9 +1918,6 @@ i915_gem_object_move_to_inactive(struct
 	BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
 	BUG_ON(!obj->active);
 
-	if (obj->pin_count) /* are we a framebuffer? */
-		intel_mark_fb_idle(obj);
-
 	list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
 	list_del_init(&obj->ring_list);
@@ -2665,17 +2662,35 @@ static inline int fence_number(struct dr
 	return fence - dev_priv->fence_regs;
 }
 
+static void i915_gem_write_fence__ipi(void *data)
+{
+	wbinvd();
+}
+
 static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
 					 struct drm_i915_fence_reg *fence,
 					 bool enable)
 {
-	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-	int reg = fence_number(dev_priv, fence);
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int fence_reg = fence_number(dev_priv, fence);
 
-	i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
+	/* In order to fully serialize access to the fenced region and
+	 * the update to the fence register we need to take extreme
+	 * measures on SNB+. In theory, the write to the fence register
+	 * flushes all memory transactions before, and coupled with the
+	 * mb() placed around the register write we serialise all memory
+	 * operations with respect to the changes in the tiler. Yet, on
+	 * SNB+ we need to take a step further and emit an explicit wbinvd()
+	 * on each processor in order to manually flush all memory
+	 * transactions before updating the fence register.
+	 */
+	if (HAS_LLC(obj->base.dev))
+		on_each_cpu(i915_gem_write_fence__ipi, NULL, 1);
+	i915_gem_write_fence(dev, fence_reg, enable ? obj : NULL);
 
 	if (enable) {
-		obj->fence_reg = reg;
+		obj->fence_reg = fence_reg;
 		fence->obj = obj;
 		list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
 	} else {
@@ -3848,7 +3863,7 @@ void i915_gem_l3_remap(struct drm_device
 	u32 misccpctl;
 	int i;
 
-	if (!IS_IVYBRIDGE(dev))
+	if (!HAS_L3_GPU_CACHE(dev))
 		return;
 
 	if (!dev_priv->l3_parity.remap_info)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem_context.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem_context.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem_context.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem_context.c	2013-05-11 16:57:46.000000000 -0400
@@ -157,6 +157,13 @@ create_hw_context(struct drm_device *dev
 		return ERR_PTR(-ENOMEM);
 	}
 
+	if (INTEL_INFO(dev)->gen >= 7) {
+		ret = i915_gem_object_set_cache_level(ctx->obj,
+						      I915_CACHE_LLC_MLC);
+		if (ret)
+			goto err_out;
+	}
+
 	/* The ring associated with the context object is handled by the normal
 	 * object tracking code. We give an initial ring value simple to pass an
 	 * assertion in the context switch code.
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2013-05-11 16:57:46.000000000 -0400
@@ -43,7 +43,7 @@ eb_create(int size)
 {
 	struct eb_objects *eb;
 	int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
-	BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
+	BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
 	while (count > size)
 		count >>= 1;
 	eb = kzalloc(count*sizeof(struct hlist_head) +
@@ -706,15 +706,20 @@ validate_exec_list(struct drm_i915_gem_e
 		   int count)
 {
 	int i;
+	int relocs_total = 0;
+	int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
 
 	for (i = 0; i < count; i++) {
 		char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
 		int length; /* limited by fault_in_pages_readable() */
 
-		/* First check for malicious input causing overflow */
-		if (exec[i].relocation_count >
-		    INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
+		/* First check for malicious input causing overflow in
+		 * the worst case where we need to allocate the entire
+		 * relocation tree as a single array.
+		 */
+		if (exec[i].relocation_count > relocs_max - relocs_total)
 			return -EINVAL;
+		relocs_total += exec[i].relocation_count;
 
 		length = exec[i].relocation_count *
 			sizeof(struct drm_i915_gem_relocation_entry);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem_stolen.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem_stolen.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_gem_stolen.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_gem_stolen.c	2013-05-11 16:57:46.000000000 -0400
@@ -42,56 +42,50 @@
  * for is a boon.
  */
 
-#define PTE_ADDRESS_MASK		0xfffff000
-#define PTE_ADDRESS_MASK_HIGH		0x000000f0 /* i915+ */
-#define PTE_MAPPING_TYPE_UNCACHED	(0 << 1)
-#define PTE_MAPPING_TYPE_DCACHE		(1 << 1) /* i830 only */
-#define PTE_MAPPING_TYPE_CACHED		(3 << 1)
-#define PTE_MAPPING_TYPE_MASK		(3 << 1)
-#define PTE_VALID			(1 << 0)
-
-/**
- * i915_stolen_to_phys - take an offset into stolen memory and turn it into
- *                       a physical one
- * @dev: drm device
- * @offset: address to translate
- *
- * Some chip functions require allocations from stolen space and need the
- * physical address of the memory in question.
- */
-static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
+static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct pci_dev *pdev = dev_priv->bridge_dev;
 	u32 base;
 
-#if 0
 	/* On the machines I have tested the Graphics Base of Stolen Memory
-	 * is unreliable, so compute the base by subtracting the stolen memory
-	 * from the Top of Low Usable DRAM which is where the BIOS places
-	 * the graphics stolen memory.
+	 * is unreliable, so on those compute the base by subtracting the
+	 * stolen memory from the Top of Low Usable DRAM which is where the
+	 * BIOS places the graphics stolen memory.
+	 *
+	 * On gen2, the layout is slightly different with the Graphics Segment
+	 * immediately following Top of Memory (or Top of Usable DRAM). Note
+	 * it appears that TOUD is only reported by 865g, so we just use the
+	 * top of memory as determined by the e820 probe.
+	 *
+	 * XXX gen2 requires an unavailable symbol and 945gm fails with
+	 * its value of TOLUD.
 	 */
-	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-		/* top 32bits are reserved = 0 */
+	base = 0;
+	if (INTEL_INFO(dev)->gen >= 6) {
+		/* Read Base Data of Stolen Memory Register (BDSM) directly.
+		 * Note that there is also a MCHBAR miror at 0x1080c0 or
+		 * we could use device 2:0x5c instead.
+		*/
+		pci_read_config_dword(pdev, 0xB0, &base);
+		base &= ~4095; /* lower bits used for locking register */
+	} else if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
+		/* Read Graphics Base of Stolen Memory directly */
 		pci_read_config_dword(pdev, 0xA4, &base);
-	} else {
-		/* XXX presume 8xx is the same as i915 */
-		pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
-	}
-#else
-	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-		u16 val;
-		pci_read_config_word(pdev, 0xb0, &val);
-		base = val >> 4 << 20;
-	} else {
+#if 0
+	} else if (IS_GEN3(dev)) {
 		u8 val;
+		/* Stolen is immediately below Top of Low Usable DRAM */
 		pci_read_config_byte(pdev, 0x9c, &val);
 		base = val >> 3 << 27;
-	}
-	base -= dev_priv->mm.gtt->stolen_size;
+		base -= dev_priv->mm.gtt->stolen_size;
+	} else {
+		/* Stolen is immediately above Top of Memory */
+		base = max_low_pfn_mapped << PAGE_SHIFT;
 #endif
+	}
 
-	return base + offset;
+	return base;
 }
 
 static void i915_warn_stolen(struct drm_device *dev)
@@ -116,7 +110,7 @@ static void i915_setup_compression(struc
 	if (!compressed_fb)
 		goto err;
 
-	cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
+	cfb_base = dev_priv->mm.stolen_base + compressed_fb->start;
 	if (!cfb_base)
 		goto err_fb;
 
@@ -129,7 +123,7 @@ static void i915_setup_compression(struc
 		if (!compressed_llb)
 			goto err_fb;
 
-		ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
+		ll_base = dev_priv->mm.stolen_base + compressed_llb->start;
 		if (!ll_base)
 			goto err_llb;
 	}
@@ -148,7 +142,7 @@ static void i915_setup_compression(struc
 	}
 
 	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
-		      cfb_base, ll_base, size >> 20);
+		      (long)cfb_base, (long)ll_base, size >> 20);
 	return;
 
 err_llb:
@@ -180,6 +174,13 @@ int i915_gem_init_stolen(struct drm_devi
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long prealloc_size = dev_priv->mm.gtt->stolen_size;
 
+	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
+	if (dev_priv->mm.stolen_base == 0)
+		return 0;
+
+	DRM_DEBUG_KMS("found %d bytes of stolen memory at %08lx\n",
+		      dev_priv->mm.gtt->stolen_size, dev_priv->mm.stolen_base);
+
 	/* Basic memrange allocator for stolen space */
 	drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/i915_reg.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/i915_reg.h	2013-05-11 16:57:46.000000000 -0400
@@ -3839,7 +3839,7 @@
 #define _TRANSB_CHICKEN2	 0xf1064
 #define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
 #define  TRANS_CHICKEN2_TIMING_OVERRIDE		(1<<31)
-
+#define  TRANS_CHICKEN2_FDI_POLARITY_REVERSED	(1<<29)
 
 #define SOUTH_CHICKEN1		0xc2000
 #define  FDIA_PHASE_SYNC_SHIFT_OVR	19
@@ -3927,7 +3927,7 @@
 #define  FDI_10BPC                      (1<<16)
 #define  FDI_6BPC                       (2<<16)
 #define  FDI_12BPC                      (3<<16)
-#define  FDI_LINK_REVERSE_OVERWRITE     (1<<15)
+#define  FDI_RX_LINK_REVERSAL_OVERRIDE  (1<<15)
 #define  FDI_DMI_LINK_REVERSE_MASK      (1<<14)
 #define  FDI_RX_PLL_ENABLE              (1<<13)
 #define  FDI_FS_ERR_CORRECT_ENABLE      (1<<11)
@@ -4211,7 +4211,9 @@
 #define GEN6_RP_INTERRUPT_LIMITS		0xA014
 #define GEN6_RPSTAT1				0xA01C
 #define   GEN6_CAGF_SHIFT			8
+#define   HSW_CAGF_SHIFT			7
 #define   GEN6_CAGF_MASK			(0x7f << GEN6_CAGF_SHIFT)
+#define   HSW_CAGF_MASK				(0x7f << HSW_CAGF_SHIFT)
 #define GEN6_RP_CONTROL				0xA024
 #define   GEN6_RP_MEDIA_TURBO			(1<<11)
 #define   GEN6_RP_MEDIA_MODE_MASK		(3<<9)
@@ -4280,8 +4282,8 @@
 #define   GEN6_PCODE_READ_MIN_FREQ_TABLE	0x9
 #define	  GEN6_PCODE_WRITE_RC6VIDS		0x4
 #define	  GEN6_PCODE_READ_RC6VIDS		0x5
-#define   GEN6_ENCODE_RC6_VID(mv)		(((mv) / 5) - 245) < 0 ?: 0
-#define   GEN6_DECODE_RC6_VID(vids)		(((vids) * 5) > 0 ? ((vids) * 5) + 245 : 0)
+#define   GEN6_ENCODE_RC6_VID(mv)		(((mv) - 245) / 5)
+#define   GEN6_DECODE_RC6_VID(vids)		(((vids) * 5) + 245)
 #define GEN6_PCODE_DATA				0x138128
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 
@@ -4524,6 +4526,7 @@
 #define  DDI_BUF_EMP_800MV_0DB_HSW		(7<<24)   /* Sel7 */
 #define  DDI_BUF_EMP_800MV_3_5DB_HSW		(8<<24)   /* Sel8 */
 #define  DDI_BUF_EMP_MASK			(0xf<<24)
+#define  DDI_BUF_PORT_REVERSAL			(1<<16)
 #define  DDI_BUF_IS_IDLE			(1<<7)
 #define  DDI_A_4_LANES				(1<<4)
 #define  DDI_PORT_WIDTH_X1			(0<<1)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_bios.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_bios.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_bios.c	2013-05-11 16:57:46.000000000 -0400
@@ -351,12 +351,14 @@ parse_general_features(struct drm_i915_p
 		dev_priv->lvds_ssc_freq =
 			intel_bios_ssc_frequency(dev, general->ssc_freq);
 		dev_priv->display_clock_mode = general->display_clock_mode;
-		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
+		dev_priv->fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
+		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
 			      dev_priv->int_tv_support,
 			      dev_priv->int_crt_support,
 			      dev_priv->lvds_use_ssc,
 			      dev_priv->lvds_ssc_freq,
-			      dev_priv->display_clock_mode);
+			      dev_priv->display_clock_mode,
+			      dev_priv->fdi_rx_polarity_inverted);
 	}
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_bios.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_bios.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_bios.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_bios.h	2013-05-11 16:57:46.000000000 -0400
@@ -127,7 +127,9 @@ struct bdb_general_features {
         /* bits 3 */
 	u8 disable_smooth_vision:1;
 	u8 single_dvi:1;
-	u8 rsvd9:6; /* finish byte */
+	u8 rsvd9:1;
+	u8 fdi_rx_polarity_inverted:1;
+	u8 rsvd10:4; /* finish byte */
 
         /* bits 4 */
 	u8 legacy_monitor_detect;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_crt.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_crt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_crt.c	2013-05-11 16:57:46.000000000 -0400
@@ -45,6 +45,9 @@
 
 struct intel_crt {
 	struct intel_encoder base;
+	/* DPMS state is stored in the connector, which we need in the
+	 * encoder's enable/disable callbacks */
+	struct intel_connector *connector;
 	bool force_hotplug_required;
 	u32 adpa_reg;
 };
@@ -81,29 +84,6 @@ static bool intel_crt_get_hw_state(struc
 	return true;
 }
 
-static void intel_disable_crt(struct intel_encoder *encoder)
-{
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_crt *crt = intel_encoder_to_crt(encoder);
-	u32 temp;
-
-	temp = I915_READ(crt->adpa_reg);
-	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-	temp &= ~ADPA_DAC_ENABLE;
-	I915_WRITE(crt->adpa_reg, temp);
-}
-
-static void intel_enable_crt(struct intel_encoder *encoder)
-{
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_crt *crt = intel_encoder_to_crt(encoder);
-	u32 temp;
-
-	temp = I915_READ(crt->adpa_reg);
-	temp |= ADPA_DAC_ENABLE;
-	I915_WRITE(crt->adpa_reg, temp);
-}
-
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -135,6 +115,19 @@ static void intel_crt_set_dpms(struct in
 	I915_WRITE(crt->adpa_reg, temp);
 }
 
+static void intel_disable_crt(struct intel_encoder *encoder)
+{
+	intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void intel_enable_crt(struct intel_encoder *encoder)
+{
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+
+	intel_crt_set_dpms(encoder, crt->connector->base.dpms);
+}
+
+
 static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
 	struct drm_device *dev = connector->dev;
@@ -746,6 +739,7 @@ void intel_crt_init(struct drm_device *d
 	}
 
 	connector = &intel_connector->base;
+	crt->connector = intel_connector;
 	drm_connector_init(dev, &intel_connector->base,
 			   &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
@@ -800,10 +794,14 @@ void intel_crt_init(struct drm_device *d
 	dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
 
 	/*
-	 * TODO: find a proper way to discover whether we need to set the
-	 * polarity reversal bit or not, instead of relying on the BIOS.
+	 * TODO: find a proper way to discover whether we need to set the the
+	 * polarity and link reversal bits or not, instead of relying on the
+	 * BIOS.
 	 */
-	if (HAS_PCH_LPT(dev))
-		dev_priv->fdi_rx_polarity_reversed =
-		     !!(I915_READ(_FDI_RXA_CTL) & FDI_RX_POLARITY_REVERSED_LPT);
+	if (HAS_PCH_LPT(dev)) {
+		u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
+				 FDI_RX_LINK_REVERSAL_OVERRIDE;
+
+		dev_priv->fdi_rx_config = I915_READ(_FDI_RXA_CTL) & fdi_config;
+	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_ddi.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_ddi.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_ddi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_ddi.c	2013-05-11 16:57:46.000000000 -0400
@@ -178,10 +178,8 @@ void hsw_fdi_link_train(struct drm_crtc
 				  FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
 
 	/* Enable the PCH Receiver FDI PLL */
-	rx_ctl_val = FDI_RX_PLL_ENABLE | FDI_RX_ENHANCE_FRAME_ENABLE |
-		     ((intel_crtc->fdi_lanes - 1) << 19);
-	if (dev_priv->fdi_rx_polarity_reversed)
-		rx_ctl_val |= FDI_RX_POLARITY_REVERSED_LPT;
+	rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
+		     FDI_RX_PLL_ENABLE | ((intel_crtc->fdi_lanes - 1) << 19);
 	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
 	POSTING_READ(_FDI_RXA_CTL);
 	udelay(220);
@@ -203,7 +201,10 @@ void hsw_fdi_link_train(struct drm_crtc
 					DP_TP_CTL_LINK_TRAIN_PAT1 |
 					DP_TP_CTL_ENABLE);
 
-		/* Configure and enable DDI_BUF_CTL for DDI E with next voltage */
+		/* Configure and enable DDI_BUF_CTL for DDI E with next voltage.
+		 * DDI E does not support port reversal, the functionality is
+		 * achieved on the PCH side in FDI_RX_CTL, so no need to set the
+		 * port reversal bit */
 		I915_WRITE(DDI_BUF_CTL(PORT_E),
 			   DDI_BUF_CTL_ENABLE |
 			   ((intel_crtc->fdi_lanes - 1) << 1) |
@@ -677,8 +678,11 @@ static void intel_ddi_mode_set(struct dr
 
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		struct intel_digital_port *intel_dig_port =
+			enc_to_dig_port(encoder);
 
-		intel_dp->DP = DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
+		intel_dp->DP = intel_dig_port->port_reversal |
+			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
 		switch (intel_dp->lane_count) {
 		case 1:
 			intel_dp->DP |= DDI_PORT_WIDTH_X1;
@@ -1291,11 +1295,15 @@ static void intel_enable_ddi(struct inte
 	int type = intel_encoder->type;
 
 	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_digital_port *intel_dig_port =
+			enc_to_dig_port(encoder);
+
 		/* In HDMI/DVI mode, the port width, and swing/emphasis values
 		 * are ignored so nothing special needs to be done besides
 		 * enabling the port.
 		 */
-		I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
+		I915_WRITE(DDI_BUF_CTL(port),
+			   intel_dig_port->port_reversal | DDI_BUF_CTL_ENABLE);
 	} else if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
@@ -1457,6 +1465,7 @@ static const struct drm_encoder_helper_f
 
 void intel_ddi_init(struct drm_device *dev, enum port port)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct drm_encoder *encoder;
@@ -1497,6 +1506,8 @@ void intel_ddi_init(struct drm_device *d
 	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 
 	intel_dig_port->port = port;
+	intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
+					DDI_BUF_PORT_REVERSAL;
 	if (hdmi_connector)
 		intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
 	else
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_display.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_display.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_display.c	2013-05-11 16:57:46.000000000 -0400
@@ -154,8 +154,8 @@ static const intel_limit_t intel_limits_
 	.vco = { .min = 1400000, .max = 2800000 },
 	.n = { .min = 1, .max = 6 },
 	.m = { .min = 70, .max = 120 },
-	.m1 = { .min = 10, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
+	.m1 = { .min = 8, .max = 18 },
+	.m2 = { .min = 3, .max = 7 },
 	.p = { .min = 5, .max = 80 },
 	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 200000,
@@ -2017,18 +2017,29 @@ void intel_unpin_fb_obj(struct drm_i915_
 
 /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
  * is assumed to be a power-of-two. */
-unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
-					       unsigned int bpp,
-					       unsigned int pitch)
+unsigned long intel_gen4_compute_page_offset(int *x, int *y,
+					     unsigned int tiling_mode,
+					     unsigned int cpp,
+					     unsigned int pitch)
 {
-	int tile_rows, tiles;
+	if (tiling_mode != I915_TILING_NONE) {
+		unsigned int tile_rows, tiles;
 
-	tile_rows = *y / 8;
-	*y %= 8;
-	tiles = *x / (512/bpp);
-	*x %= 512/bpp;
+		tile_rows = *y / 8;
+		*y %= 8;
 
-	return tile_rows * pitch * 8 + tiles * 4096;
+		tiles = *x / (512/cpp);
+		*x %= 512/cpp;
+
+		return tile_rows * pitch * 8 + tiles * 4096;
+	} else {
+		unsigned int offset;
+
+		offset = *y * pitch + *x * cpp;
+		*y = 0;
+		*x = (offset & 4095) / cpp;
+		return offset & -4096;
+	}
 }
 
 static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
@@ -2105,9 +2116,9 @@ static int i9xx_update_plane(struct drm_
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
-			intel_gen4_compute_offset_xtiled(&x, &y,
-							 fb->bits_per_pixel / 8,
-							 fb->pitches[0]);
+			intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
+						       fb->bits_per_pixel / 8,
+						       fb->pitches[0]);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
 		intel_crtc->dspaddr_offset = linear_offset;
@@ -2198,9 +2209,9 @@ static int ironlake_update_plane(struct
 
 	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
 	intel_crtc->dspaddr_offset =
-		intel_gen4_compute_offset_xtiled(&x, &y,
-						 fb->bits_per_pixel / 8,
-						 fb->pitches[0]);
+		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
+					       fb->bits_per_pixel / 8,
+					       fb->pitches[0]);
 	linear_offset -= intel_crtc->dspaddr_offset;
 
 	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
@@ -3686,6 +3697,7 @@ static void i9xx_crtc_disable(struct drm
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
+	u32 pctl;
 
 
 	if (!intel_crtc->active)
@@ -3705,6 +3717,13 @@ static void i9xx_crtc_disable(struct drm
 
 	intel_disable_plane(dev_priv, plane, pipe);
 	intel_disable_pipe(dev_priv, pipe);
+
+	/* Disable pannel fitter if it is on this pipe. */
+	pctl = I915_READ(PFIT_CONTROL);
+	if ((pctl & PFIT_ENABLE) &&
+	    ((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe)
+		I915_WRITE(PFIT_CONTROL, 0);
+
 	intel_disable_pll(dev_priv, pipe);
 
 	intel_crtc->active = false;
@@ -6993,11 +7012,6 @@ void intel_mark_busy(struct drm_device *
 
 void intel_mark_idle(struct drm_device *dev)
 {
-}
-
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
-{
-	struct drm_device *dev = obj->base.dev;
 	struct drm_crtc *crtc;
 
 	if (!i915_powersave)
@@ -7007,12 +7021,11 @@ void intel_mark_fb_busy(struct drm_i915_
 		if (!crtc->fb)
 			continue;
 
-		if (to_intel_framebuffer(crtc->fb)->obj == obj)
-			intel_increase_pllclock(crtc);
+		intel_decrease_pllclock(crtc);
 	}
 }
 
-void intel_mark_fb_idle(struct drm_i915_gem_object *obj)
+void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_crtc *crtc;
@@ -7025,7 +7038,7 @@ void intel_mark_fb_idle(struct drm_i915_
 			continue;
 
 		if (to_intel_framebuffer(crtc->fb)->obj == obj)
-			intel_decrease_pllclock(crtc);
+			intel_increase_pllclock(crtc);
 	}
 }
 
@@ -7407,8 +7420,8 @@ static int intel_crtc_page_flip(struct d
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj;
+	struct drm_framebuffer *old_fb = crtc->fb;
+	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_unpin_work *work;
 	unsigned long flags;
@@ -7433,8 +7446,7 @@ static int intel_crtc_page_flip(struct d
 
 	work->event = event;
 	work->crtc = crtc;
-	intel_fb = to_intel_framebuffer(crtc->fb);
-	work->old_fb_obj = intel_fb->obj;
+	work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
 	INIT_WORK(&work->work, intel_unpin_work_fn);
 
 	ret = drm_vblank_get(dev, intel_crtc->pipe);
@@ -7454,9 +7466,6 @@ static int intel_crtc_page_flip(struct d
 	intel_crtc->unpin_work = work;
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
-	intel_fb = to_intel_framebuffer(fb);
-	obj = intel_fb->obj;
-
 	if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
 		flush_workqueue(dev_priv->wq);
 
@@ -7494,6 +7503,7 @@ static int intel_crtc_page_flip(struct d
 
 cleanup_pending:
 	atomic_dec(&intel_crtc->unpin_work_count);
+	crtc->fb = old_fb;
 	atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
 	drm_gem_object_unreference(&work->old_fb_obj->base);
 	drm_gem_object_unreference(&obj->base);
@@ -7722,22 +7732,25 @@ intel_modeset_affected_pipes(struct drm_
 	if (crtc->enabled)
 		*prepare_pipes |= 1 << intel_crtc->pipe;
 
-	/* We only support modeset on one single crtc, hence we need to do that
-	 * only for the passed in crtc iff we change anything else than just
-	 * disable crtcs.
-	 *
-	 * This is actually not true, to be fully compatible with the old crtc
-	 * helper we automatically disable _any_ output (i.e. doesn't need to be
-	 * connected to the crtc we're modesetting on) if it's disconnected.
-	 * Which is a rather nutty api (since changed the output configuration
-	 * without userspace's explicit request can lead to confusion), but
-	 * alas. Hence we currently need to modeset on all pipes we prepare. */
+	/*
+	 * For simplicity do a full modeset on any pipe where the output routing
+	 * changed. We could be more clever, but that would require us to be
+	 * more careful with calling the relevant encoder->mode_set functions.
+	 */
 	if (*prepare_pipes)
 		*modeset_pipes = *prepare_pipes;
 
 	/* ... and mask these out. */
 	*modeset_pipes &= ~(*disable_pipes);
 	*prepare_pipes &= ~(*disable_pipes);
+
+	/*
+	 * HACK: We don't (yet) fully support global modesets. intel_set_config
+	 * obies this rule, but the modeset restore mode of
+	 * intel_modeset_setup_hw_state does not.
+	 */
+	*modeset_pipes &= 1 << intel_crtc->pipe;
+	*prepare_pipes &= 1 << intel_crtc->pipe;
 }
 
 static bool intel_crtc_in_use(struct drm_crtc *crtc)
@@ -8888,6 +8901,18 @@ static struct intel_quirk intel_quirks[]
 
 	/* Acer Aspire 5734Z must invert backlight brightness */
 	{ 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
+
+	/* Acer Aspire 4736Z */
+	{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
+
+	/* Acer/eMachines G725 */
+	{ 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
+
+	/* Acer/eMachines e725 */
+	{ 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
+
+	/* Acer/Packard Bell NCL20 */
+	{ 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -9366,6 +9391,9 @@ void intel_modeset_cleanup(struct drm_de
 	/* flush any delayed tasks or pending work */
 	flush_scheduled_work();
 
+	/* destroy backlight, if any, before the connectors */
+	intel_panel_destroy_backlight(dev);
+
 	drm_mode_config_cleanup(dev);
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_dp.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_dp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_dp.c	2013-05-11 16:57:46.000000000 -0400
@@ -788,6 +788,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc,
 	struct intel_dp_m_n m_n;
 	int pipe = intel_crtc->pipe;
 	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	int target_clock;
 
 	/*
 	 * Find the lane count in the intel_encoder private
@@ -803,13 +804,22 @@ intel_dp_set_m_n(struct drm_crtc *crtc,
 		}
 	}
 
+	target_clock = mode->clock;
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+			target_clock = intel_edp_target_clock(intel_encoder,
+							      mode);
+			break;
+		}
+	}
+
 	/*
 	 * Compute the GMCH and Link ratios. The '3' here is
 	 * the number of bytes_per_pixel post-LUT, which we always
 	 * set up for 8-bits of R/G/B, or 3 bytes total.
 	 */
 	intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
-			     mode->clock, adjusted_mode->clock, &m_n);
+			     target_clock, adjusted_mode->clock, &m_n);
 
 	if (IS_HASWELL(dev)) {
 		I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
@@ -1850,7 +1860,7 @@ intel_dp_start_link_train(struct intel_d
 		for (i = 0; i < intel_dp->lane_count; i++)
 			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
 				break;
-		if (i == intel_dp->lane_count && voltage_tries == 5) {
+		if (i == intel_dp->lane_count) {
 			++loop_tries;
 			if (loop_tries == 5) {
 				DRM_DEBUG_KMS("too many full retries, give up\n");
@@ -2457,17 +2467,14 @@ done:
 static void
 intel_dp_destroy(struct drm_connector *connector)
 {
-	struct drm_device *dev = connector->dev;
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 
 	if (!IS_ERR_OR_NULL(intel_connector->edid))
 		kfree(intel_connector->edid);
 
-	if (is_edp(intel_dp)) {
-		intel_panel_destroy_backlight(dev);
+	if (is_edp(intel_dp))
 		intel_panel_fini(&intel_connector->panel);
-	}
 
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_drv.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_drv.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_drv.h	2013-05-11 16:57:46.000000000 -0400
@@ -377,6 +377,7 @@ struct intel_dp {
 struct intel_digital_port {
 	struct intel_encoder base;
 	enum port port;
+	u32 port_reversal;
 	struct intel_dp dp;
 	struct intel_hdmi hdmi;
 };
@@ -439,9 +440,8 @@ extern bool intel_sdvo_init(struct drm_d
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_mark_busy(struct drm_device *dev);
-extern void intel_mark_idle(struct drm_device *dev);
 extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
-extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);
+extern void intel_mark_idle(struct drm_device *dev);
 extern bool intel_lvds_init(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int output_reg,
 			  enum port port);
@@ -627,9 +627,10 @@ extern void intel_update_sprite_watermar
 extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe,
 			 struct drm_display_mode *mode);
 
-extern unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
-						      unsigned int bpp,
-						      unsigned int pitch);
+extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
+						    unsigned int tiling_mode,
+						    unsigned int bpp,
+						    unsigned int pitch);
 
 extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 				     struct drm_file *file_priv);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_dvo.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_dvo.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_dvo.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_dvo.c	2013-05-11 16:57:46.000000000 -0400
@@ -449,6 +449,7 @@ void intel_dvo_init(struct drm_device *d
 		const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
 		struct i2c_adapter *i2c;
 		int gpio;
+		bool dvoinit;
 
 		/* Allow the I2C driver info to specify the GPIO to be used in
 		 * special cases, but otherwise default to what's defined
@@ -468,7 +469,17 @@ void intel_dvo_init(struct drm_device *d
 		i2c = intel_gmbus_get_adapter(dev_priv, gpio);
 
 		intel_dvo->dev = *dvo;
-		if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
+
+		/* GMBUS NAK handling seems to be unstable, hence let the
+		 * transmitter detection run in bit banging mode for now.
+		 */
+		intel_gmbus_force_bit(i2c, true);
+
+		dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c);
+
+		intel_gmbus_force_bit(i2c, false);
+
+		if (!dvoinit)
 			continue;
 
 		intel_encoder->type = INTEL_OUTPUT_DVO;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_lvds.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_lvds.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_lvds.c	2013-05-11 16:57:46.000000000 -0400
@@ -556,7 +556,6 @@ static void intel_lvds_destroy(struct dr
 	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
 		kfree(lvds_connector->base.edid);
 
-	intel_panel_destroy_backlight(connector->dev);
 	intel_panel_fini(&lvds_connector->base.panel);
 
 	drm_sysfs_connector_remove(connector);
@@ -790,6 +789,14 @@ static const struct dmi_system_id intel_
 			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Fujitsu Esprimo Q900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_panel.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_panel.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_panel.c	2013-05-11 16:57:46.000000000 -0400
@@ -422,6 +422,9 @@ int intel_panel_setup_backlight(struct d
 
 	intel_panel_init_backlight(dev);
 
+	if (WARN_ON(dev_priv->backlight))
+		return -ENODEV;
+
 	memset(&props, 0, sizeof(props));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = _intel_panel_get_max_backlight(dev);
@@ -447,8 +450,10 @@ int intel_panel_setup_backlight(struct d
 void intel_panel_destroy_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	if (dev_priv->backlight)
+	if (dev_priv->backlight) {
 		backlight_device_unregister(dev_priv->backlight);
+		dev_priv->backlight = NULL;
+	}
 }
 #else
 int intel_panel_setup_backlight(struct drm_connector *connector)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_pm.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_pm.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_pm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_pm.c	2013-05-11 16:57:46.000000000 -0400
@@ -2572,7 +2572,7 @@ static void gen6_enable_rps(struct drm_d
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
 	I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
-	I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
+	I915_WRITE(GEN6_RC6p_THRESHOLD, 150000);
 	I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
 
 	/* Check if we are enabling RC6 */
@@ -3560,6 +3560,7 @@ static void cpt_init_clock_gating(struct
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
+	uint32_t val;
 
 	/*
 	 * On Ibex Peak and Cougar Point, we need to disable clock
@@ -3572,8 +3573,12 @@ static void cpt_init_clock_gating(struct
 	/* The below fixes the weird display corruption, a few pixels shifted
 	 * downward, on (only) LVDS of some HP laptops with IVY.
 	 */
-	for_each_pipe(pipe)
-		I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_CHICKEN2_TIMING_OVERRIDE);
+	for_each_pipe(pipe) {
+		val = TRANS_CHICKEN2_TIMING_OVERRIDE;
+		if (dev_priv->fdi_rx_polarity_inverted)
+			val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
+		I915_WRITE(TRANS_CHICKEN2(pipe), val);
+	}
 	/* WADP0ClockGatingDisable */
 	for_each_pipe(pipe) {
 		I915_WRITE(TRANS_CHICKEN1(pipe),
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_sdvo.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_sdvo.c	2013-05-11 16:57:46.000000000 -0400
@@ -1213,11 +1213,13 @@ static bool intel_sdvo_get_hw_state(stru
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	u16 active_outputs;
 	u32 tmp;
 
 	tmp = I915_READ(intel_sdvo->sdvo_reg);
+	intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
 
-	if (!(tmp & SDVO_ENABLE))
+	if (!(tmp & SDVO_ENABLE) && (active_outputs == 0))
 		return false;
 
 	if (HAS_PCH_CPT(dev))
@@ -2704,7 +2706,6 @@ bool intel_sdvo_init(struct drm_device *
 	struct intel_sdvo *intel_sdvo;
 	u32 hotplug_mask;
 	int i;
-
 	intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
 	if (!intel_sdvo)
 		return false;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_sprite.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_sprite.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/i915/intel_sprite.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/i915/intel_sprite.c	2013-05-11 16:57:46.000000000 -0400
@@ -122,8 +122,8 @@ ivb_update_plane(struct drm_plane *plane
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset =
-		intel_gen4_compute_offset_xtiled(&x, &y,
-						 pixel_size, fb->pitches[0]);
+		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
+					       pixel_size, fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
@@ -287,8 +287,8 @@ ilk_update_plane(struct drm_plane *plane
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset =
-		intel_gen4_compute_offset_xtiled(&x, &y,
-						 pixel_size, fb->pitches[0]);
+		intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
+					       pixel_size, fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
 	if (obj->tiling_mode != I915_TILING_NONE)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_drv.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_drv.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_drv.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_drv.h	2013-05-11 16:57:46.000000000 -0400
@@ -116,6 +116,8 @@ struct mga_fbdev {
 	void *sysram;
 	int size;
 	struct ttm_bo_kmap_obj mapping;
+	int x1, y1, x2, y2; /* dirty rect */
+	spinlock_t dirty_lock;
 };
 
 struct mga_crtc {
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_fb.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_fb.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_fb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_fb.c	2013-05-11 16:57:46.000000000 -0400
@@ -28,16 +28,52 @@ static void mga_dirty_update(struct mga_
 	int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8;
 	int ret;
 	bool unmap = false;
+	bool store_for_later = false;
+	int x2, y2;
+	unsigned long flags;
 
 	obj = mfbdev->mfb.obj;
 	bo = gem_to_mga_bo(obj);
 
+	/*
+	 * try and reserve the BO, if we fail with busy
+	 * then the BO is being moved and we should
+	 * store up the damage until later.
+	 */
 	ret = mgag200_bo_reserve(bo, true);
 	if (ret) {
-		DRM_ERROR("failed to reserve fb bo\n");
+		if (ret != -EBUSY)
+			return;
+
+		store_for_later = true;
+	}
+
+	x2 = x + width - 1;
+	y2 = y + height - 1;
+	spin_lock_irqsave(&mfbdev->dirty_lock, flags);
+
+	if (mfbdev->y1 < y)
+		y = mfbdev->y1;
+	if (mfbdev->y2 > y2)
+		y2 = mfbdev->y2;
+	if (mfbdev->x1 < x)
+		x = mfbdev->x1;
+	if (mfbdev->x2 > x2)
+		x2 = mfbdev->x2;
+
+	if (store_for_later) {
+		mfbdev->x1 = x;
+		mfbdev->x2 = x2;
+		mfbdev->y1 = y;
+		mfbdev->y2 = y2;
+		spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
 		return;
 	}
 
+	mfbdev->x1 = mfbdev->y1 = INT_MAX;
+	mfbdev->x2 = mfbdev->y2 = 0;
+	spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
+
 	if (!bo->kmap.virtual) {
 		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
 		if (ret) {
@@ -47,10 +83,10 @@ static void mga_dirty_update(struct mga_
 		}
 		unmap = true;
 	}
-	for (i = y; i < y + height; i++) {
+	for (i = y; i <= y2; i++) {
 		/* assume equal stride for now */
 		src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp);
-		memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, width * bpp);
+		memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp);
 
 	}
 	if (unmap)
@@ -269,6 +305,7 @@ int mgag200_fbdev_init(struct mga_device
 
 	mdev->mfbdev = mfbdev;
 	mfbdev->helper.funcs = &mga_fb_helper_funcs;
+	spin_lock_init(&mfbdev->dirty_lock);
 
 	ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
 				 mdev->num_crtc, MGAG200FB_CONN_LIMIT);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_mode.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_mode.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_mode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_mode.c	2013-05-11 16:57:46.000000000 -0400
@@ -382,19 +382,19 @@ static int mga_g200eh_set_plls(struct mg
 	m = n = p = 0;
 	vcomax = 800000;
 	vcomin = 400000;
-	pllreffreq = 3333;
+	pllreffreq = 33333;
 
 	delta = 0xffffffff;
 	permitteddelta = clock * 5 / 1000;
 
-	for (testp = 16; testp > 0; testp--) {
+	for (testp = 16; testp > 0; testp >>= 1) {
 		if (clock * testp > vcomax)
 			continue;
 		if (clock * testp < vcomin)
 			continue;
 
 		for (testm = 1; testm < 33; testm++) {
-			for (testn = 1; testn < 257; testn++) {
+			for (testn = 17; testn < 257; testn++) {
 				computed = (pllreffreq * testn) /
 					(testm * testp);
 				if (computed > clock)
@@ -404,11 +404,11 @@ static int mga_g200eh_set_plls(struct mg
 				if (tmpdelta < delta) {
 					delta = tmpdelta;
 					n = testn - 1;
-					m = (testm - 1) | ((n >> 1) & 0x80);
+					m = (testm - 1);
 					p = testp - 1;
 				}
 				if ((clock * testp) >= 600000)
-					p |= 80;
+					p |= 0x80;
 			}
 		}
 	}
@@ -751,8 +751,6 @@ static int mga_crtc_mode_set(struct drm_
 	int i;
 	unsigned char misc = 0;
 	unsigned char ext_vga[6];
-	unsigned char ext_vga_index24;
-	unsigned char dac_index90 = 0;
 	u8 bppshift;
 
 	static unsigned char dacvalue[] = {
@@ -803,7 +801,6 @@ static int mga_crtc_mode_set(struct drm_
 		option2 = 0x0000b000;
 		break;
 	case G200_ER:
-		dac_index90 = 0;
 		break;
 	}
 
@@ -852,10 +849,8 @@ static int mga_crtc_mode_set(struct drm_
 		WREG_DAC(i, dacvalue[i]);
 	}
 
-	if (mdev->type == G200_ER) {
-		WREG_DAC(0x90, dac_index90);
-	}
-
+	if (mdev->type == G200_ER)
+		WREG_DAC(0x90, 0);
 
 	if (option)
 		pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option);
@@ -952,8 +947,6 @@ static int mga_crtc_mode_set(struct drm_
 	if (mdev->type == G200_WB)
 		ext_vga[1] |= 0x88;
 
-	ext_vga_index24 = 0x05;
-
 	/* Set pixel clocks */
 	misc = 0x2d;
 	WREG8(MGA_MISC_OUT, misc);
@@ -965,7 +958,7 @@ static int mga_crtc_mode_set(struct drm_
 	}
 
 	if (mdev->type == G200_ER)
-		WREG_ECRT(24, ext_vga_index24);
+		WREG_ECRT(0x24, 0x5);
 
 	if (mdev->type == G200_EV) {
 		WREG_ECRT(6, 0);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_ttm.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_ttm.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/mgag200/mgag200_ttm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/mgag200/mgag200_ttm.c	2013-05-11 16:57:46.000000000 -0400
@@ -315,8 +315,8 @@ int mgag200_bo_reserve(struct mgag200_bo
 
 	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
 	if (ret) {
-		if (ret != -ERESTARTSYS)
-			DRM_ERROR("reserve failed %p\n", bo);
+		if (ret != -ERESTARTSYS && ret != -EBUSY)
+			DRM_ERROR("reserve failed %p %d\n", bo, ret);
 		return ret;
 	}
 	return 0;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h	2013-05-11 16:57:46.000000000 -0400
@@ -16,6 +16,8 @@ enum dcb_output_type {
 
 struct dcb_output {
 	int index;	/* may not be raw dcb index if merging has happened */
+	u16 hasht;
+	u16 hashm;
 	enum dcb_output_type type;
 	uint8_t i2c_index;
 	uint8_t heads;
@@ -25,6 +27,7 @@ struct dcb_output {
 	uint8_t or;
 	uint8_t link;
 	bool duallink_possible;
+	uint8_t extdev;
 	union {
 		struct sor_conf {
 			int link;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c	2013-05-11 16:57:46.000000000 -0400
@@ -107,6 +107,18 @@ dcb_outp(struct nouveau_bios *bios, u8 i
 	return 0x0000;
 }
 
+static inline u16
+dcb_outp_hasht(struct dcb_output *outp)
+{
+	return (outp->extdev << 8) | (outp->location << 4) | outp->type;
+}
+
+static inline u16
+dcb_outp_hashm(struct dcb_output *outp)
+{
+	return (outp->heads << 8) | (outp->link << 6) | outp->or;
+}
+
 u16
 dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
 	       struct dcb_output *outp)
@@ -135,34 +147,28 @@ dcb_outp_parse(struct nouveau_bios *bios
 			case DCB_OUTPUT_DP:
 				outp->link = (conf & 0x00000030) >> 4;
 				outp->sorconf.link = outp->link; /*XXX*/
+				outp->extdev = 0x00;
+				if (outp->location != 0)
+					outp->extdev = (conf & 0x0000ff00) >> 8;
 				break;
 			default:
 				break;
 			}
 		}
+
+		outp->hasht = dcb_outp_hasht(outp);
+		outp->hashm = dcb_outp_hashm(outp);
 	}
 	return dcb;
 }
 
-static inline u16
-dcb_outp_hasht(struct dcb_output *outp)
-{
-	return outp->type;
-}
-
-static inline u16
-dcb_outp_hashm(struct dcb_output *outp)
-{
-	return (outp->heads << 8) | (outp->link << 6) | outp->or;
-}
-
 u16
 dcb_outp_match(struct nouveau_bios *bios, u16 type, u16 mask,
 	       u8 *ver, u8 *len, struct dcb_output *outp)
 {
 	u16 dcb, idx = 0;
 	while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) {
-		if (dcb_outp_hasht(outp) == type) {
+		if ((dcb_outp_hasht(outp) & 0x00ff) == (type & 0x00ff)) {
 			if ((dcb_outp_hashm(outp) & mask) == mask)
 				break;
 		}
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c	2013-05-11 16:57:46.000000000 -0400
@@ -78,12 +78,13 @@ nv50_devinit_init(struct nouveau_object
 	if (ret)
 		return ret;
 
-	/* if we ran the init tables, execute first script pointer for each
-	 * display table output entry that has a matching dcb entry.
+	/* if we ran the init tables, we have to execute the first script
+	 * pointer of each dcb entry's display encoder table in order
+	 * to properly initialise each encoder.
 	 */
-	while (priv->base.post && ver) {
-		u16 data = nvbios_outp_parse(bios, i++, &ver, &hdr, &cnt, &len, &info);
-		if (data && dcb_outp_match(bios, info.type, info.mask, &ver, &len, &outp)) {
+	while (priv->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
+		if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
+				     &ver, &hdr, &cnt, &len, &info)) {
 			struct nvbios_init init = {
 				.subdev = nv_subdev(priv),
 				.bios = bios,
@@ -95,7 +96,8 @@ nv50_devinit_init(struct nouveau_object
 
 			nvbios_exec(&init);
 		}
-	};
+		i++;
+	}
 
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/nouveau_abi16.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/nouveau_abi16.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/nouveau/nouveau_abi16.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/nouveau/nouveau_abi16.c	2013-05-11 16:57:46.000000000 -0400
@@ -386,7 +386,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(AB
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_device *device = nv_device(drm->device);
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-	struct nouveau_abi16_chan *chan, *temp;
+	struct nouveau_abi16_chan *chan = NULL, *temp;
 	struct nouveau_abi16_ntfy *ntfy;
 	struct nouveau_object *object;
 	struct nv_dma_class args = {};
@@ -399,10 +399,11 @@ nouveau_abi16_ioctl_notifierobj_alloc(AB
 	if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
 		return nouveau_abi16_put(abi16, -EINVAL);
 
-	list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-		if (chan->chan->handle == (NVDRM_CHAN | info->channel))
+	list_for_each_entry(temp, &abi16->channels, head) {
+		if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
+			chan = temp;
 			break;
-		chan = NULL;
+		}
 	}
 
 	if (!chan)
@@ -454,17 +455,18 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IO
 {
 	struct drm_nouveau_gpuobj_free *fini = data;
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-	struct nouveau_abi16_chan *chan, *temp;
+	struct nouveau_abi16_chan *chan = NULL, *temp;
 	struct nouveau_abi16_ntfy *ntfy;
 	int ret;
 
 	if (unlikely(!abi16))
 		return -ENOMEM;
 
-	list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-		if (chan->chan->handle == (NVDRM_CHAN | fini->channel))
+	list_for_each_entry(temp, &abi16->channels, head) {
+		if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
+			chan = temp;
 			break;
-		chan = NULL;
+		}
 	}
 
 	if (!chan)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c	2013-05-11 16:57:46.000000000 -0400
@@ -252,8 +252,6 @@ void atombios_crtc_dpms(struct drm_crtc
 		radeon_crtc->enabled = true;
 		/* adjust pm to dpms changes BEFORE enabling crtcs */
 		radeon_pm_compute_clocks(rdev);
-		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
-			atombios_powergate_crtc(crtc, ATOM_DISABLE);
 		atombios_enable_crtc(crtc, ATOM_ENABLE);
 		if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
 			atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
@@ -271,8 +269,6 @@ void atombios_crtc_dpms(struct drm_crtc
 			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
 		atombios_enable_crtc(crtc, ATOM_DISABLE);
 		radeon_crtc->enabled = false;
-		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
-			atombios_powergate_crtc(crtc, ATOM_ENABLE);
 		/* adjust pm to dpms changes AFTER disabling crtcs */
 		radeon_pm_compute_clocks(rdev);
 		break;
@@ -561,6 +557,9 @@ static u32 atombios_adjust_pll(struct dr
 		/* use frac fb div on APUs */
 		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
 			radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
+		/* use frac fb div on RS780/RS880 */
+		if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+			radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 		if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
 			radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 	} else {
@@ -1844,6 +1843,8 @@ static void atombios_crtc_disable(struct
 	int i;
 
 	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	if (ASIC_IS_DCE6(rdev))
+		atombios_powergate_crtc(crtc, ATOM_ENABLE);
 
 	for (i = 0; i < rdev->num_crtc; i++) {
 		if (rdev->mode_info.crtcs[i] &&
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/atom.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/atom.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/atom.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/atom.c	2013-05-11 16:57:46.000000000 -0400
@@ -1389,10 +1389,10 @@ int atom_allocate_fb_scratch(struct atom
 		firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
 
 		DRM_DEBUG("atom firmware requested %08x %dkb\n",
-			  firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
-			  firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
+			  le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),
+			  le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb));
 
-		usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
+		usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
 	}
 	ctx->scratch_size_bytes = 0;
 	if (usage_bytes == 0)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/evergreen.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/evergreen.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/evergreen.c	2013-05-11 16:57:46.000000000 -0400
@@ -105,6 +105,27 @@ void evergreen_fix_pci_max_read_req_size
 	}
 }
 
+static bool dce4_is_in_vblank(struct radeon_device *rdev, int crtc)
+{
+	if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+		return true;
+	else
+		return false;
+}
+
+static bool dce4_is_counter_moving(struct radeon_device *rdev, int crtc)
+{
+	u32 pos1, pos2;
+
+	pos1 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+	pos2 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+	if (pos1 != pos2)
+		return true;
+	else
+		return false;
+}
+
 /**
  * dce4_wait_for_vblank - vblank wait asic callback.
  *
@@ -115,21 +136,28 @@ void evergreen_fix_pci_max_read_req_size
  */
 void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
 {
-	int i;
+	unsigned i = 0;
 
 	if (crtc >= rdev->num_crtc)
 		return;
 
-	if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) {
-		for (i = 0; i < rdev->usec_timeout; i++) {
-			if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK))
+	if (!(RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN))
+		return;
+
+	/* depending on when we hit vblank, we may be close to active; if so,
+	 * wait for another frame.
+	 */
+	while (dce4_is_in_vblank(rdev, crtc)) {
+		if (i++ % 100 == 0) {
+			if (!dce4_is_counter_moving(rdev, crtc))
 				break;
-			udelay(1);
 		}
-		for (i = 0; i < rdev->usec_timeout; i++) {
-			if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+	}
+
+	while (!dce4_is_in_vblank(rdev, crtc)) {
+		if (i++ % 100 == 0) {
+			if (!dce4_is_counter_moving(rdev, crtc))
 				break;
-			udelay(1);
 		}
 	}
 }
@@ -403,6 +431,19 @@ void evergreen_pm_misc(struct radeon_dev
 			rdev->pm.current_vddc = voltage->voltage;
 			DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
 		}
+
+		/* starting with BTC, there is one state that is used for both
+		 * MH and SH.  Difference is that we always use the high clock index for
+		 * mclk and vddci.
+		 */
+		if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
+		    (rdev->family >= CHIP_BARTS) &&
+		    rdev->pm.active_crtc_count &&
+		    ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) ||
+		     (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX)))
+			voltage = &rdev->pm.power_state[req_ps_idx].
+				clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].voltage;
+
 		/* 0xff01 is a flag rather then an actual voltage */
 		if (voltage->vddci == 0xff01)
 			return;
@@ -595,6 +636,16 @@ void evergreen_hpd_init(struct radeon_de
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking the
+			 * aux dp channel on imac and help (but not completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			continue;
+		}
 		switch (radeon_connector->hpd.hpd) {
 		case RADEON_HPD_1:
 			WREG32(DC_HPD1_CONTROL, tmp);
@@ -1312,17 +1363,16 @@ void evergreen_mc_stop(struct radeon_dev
 				tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
 				if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
 					radeon_wait_for_vblank(rdev, i);
-					tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
 					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+					tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
 					WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
-					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
 				}
 			} else {
 				tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
 				if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {
 					radeon_wait_for_vblank(rdev, i);
-					tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
 					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+					tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
 					WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
 					WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
 				}
@@ -1334,6 +1384,15 @@ void evergreen_mc_stop(struct radeon_dev
 					break;
 				udelay(1);
 			}
+
+			/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+			WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
+			tmp &= ~EVERGREEN_CRTC_MASTER_EN;
+			WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+			WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			save->crtc_enabled[i] = false;
+			/* ***** */
 		} else {
 			save->crtc_enabled[i] = false;
 		}
@@ -1351,6 +1410,22 @@ void evergreen_mc_stop(struct radeon_dev
 	}
 	/* wait for the MC to settle */
 	udelay(100);
+
+	/* lock double buffered regs */
+	for (i = 0; i < rdev->num_crtc; i++) {
+		if (save->crtc_enabled[i]) {
+			tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
+			if (!(tmp & EVERGREEN_GRPH_UPDATE_LOCK)) {
+				tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
+				WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (!(tmp & 1)) {
+				tmp |= 1;
+				WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+		}
+	}
 }
 
 void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
@@ -1372,6 +1447,33 @@ void evergreen_mc_resume(struct radeon_d
 	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
 	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
 
+	/* unlock regs and wait for update */
+	for (i = 0; i < rdev->num_crtc; i++) {
+		if (save->crtc_enabled[i]) {
+			tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]);
+			if ((tmp & 0x3) != 0) {
+				tmp &= ~0x3;
+				WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
+			if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) {
+				tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
+				WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (tmp & 1) {
+				tmp &= ~1;
+				WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+			for (j = 0; j < rdev->usec_timeout; j++) {
+				tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
+				if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0)
+					break;
+				udelay(1);
+			}
+		}
+	}
+
 	/* unblackout the MC */
 	tmp = RREG32(MC_SHARED_BLACKOUT_CNTL);
 	tmp &= ~BLACKOUT_MODE_MASK;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h	2013-05-11 16:57:46.000000000 -0400
@@ -225,6 +225,8 @@
 #define EVERGREEN_CRTC_STATUS_POSITION                  0x6e90
 #define EVERGREEN_MASTER_UPDATE_MODE                    0x6ef8
 #define EVERGREEN_CRTC_UPDATE_LOCK                      0x6ed4
+#define EVERGREEN_MASTER_UPDATE_LOCK                    0x6ef4
+#define EVERGREEN_MASTER_UPDATE_MODE                    0x6ef8
 
 #define EVERGREEN_DC_GPIO_HPD_MASK                      0x64b0
 #define EVERGREEN_DC_GPIO_HPD_A                         0x64b4
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/ni.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/ni.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/ni.c	2013-05-01 16:38:09.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/ni.c	2013-05-11 19:14:06.000000000 -0400
@@ -422,21 +422,32 @@ static void cayman_gpu_init(struct radeo
 		    (rdev->pdev->device == 0x9907) ||
 		    (rdev->pdev->device == 0x9908) ||
 		    (rdev->pdev->device == 0x9909) ||
+		    (rdev->pdev->device == 0x990B) ||
+		    (rdev->pdev->device == 0x990C) ||
+		    (rdev->pdev->device == 0x990F) ||
 		    (rdev->pdev->device == 0x9910) ||
-		    (rdev->pdev->device == 0x9917)) {
+		    (rdev->pdev->device == 0x9917) ||
+		    (rdev->pdev->device == 0x9999) ||
+		    (rdev->pdev->device == 0x999C)) {
 			rdev->config.cayman.max_simds_per_se = 6;
 			rdev->config.cayman.max_backends_per_se = 2;
 		} else if ((rdev->pdev->device == 0x9903) ||
 			   (rdev->pdev->device == 0x9904) ||
 			   (rdev->pdev->device == 0x990A) ||
+			   (rdev->pdev->device == 0x990D) ||
+			   (rdev->pdev->device == 0x990E) ||
 			   (rdev->pdev->device == 0x9913) ||
-			   (rdev->pdev->device == 0x9918)) {
+			   (rdev->pdev->device == 0x9918) ||
+			   (rdev->pdev->device == 0x999D)) {
 			rdev->config.cayman.max_simds_per_se = 4;
 			rdev->config.cayman.max_backends_per_se = 2;
 		} else if ((rdev->pdev->device == 0x9919) ||
 			   (rdev->pdev->device == 0x9990) ||
 			   (rdev->pdev->device == 0x9991) ||
 			   (rdev->pdev->device == 0x9994) ||
+			   (rdev->pdev->device == 0x9995) ||
+			   (rdev->pdev->device == 0x9996) ||
+			   (rdev->pdev->device == 0x999A) ||
 			   (rdev->pdev->device == 0x99A0)) {
 			rdev->config.cayman.max_simds_per_se = 3;
 			rdev->config.cayman.max_backends_per_se = 1;
@@ -566,15 +577,28 @@ static void cayman_gpu_init(struct radeo
 
 	WREG32(GB_ADDR_CONFIG, gb_addr_config);
 	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
+	if (ASIC_IS_DCE6(rdev))
+		WREG32(DMIF_ADDR_CALC, gb_addr_config);
 	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
 	WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
 	WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
 
-	tmp = gb_addr_config & NUM_PIPES_MASK;
-	tmp = r6xx_remap_render_backend(rdev, tmp,
-					rdev->config.cayman.max_backends_per_se *
-					rdev->config.cayman.max_shader_engines,
-					CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+	if ((rdev->config.cayman.max_backends_per_se == 1) &&
+	    (rdev->flags & RADEON_IS_IGP)) {
+		if ((disabled_rb_mask & 3) == 1) {
+			/* RB0 disabled, RB1 enabled */
+			tmp = 0x11111111;
+		} else {
+			/* RB1 disabled, RB0 enabled */
+			tmp = 0x00000000;
+		}
+	} else {
+		tmp = gb_addr_config & NUM_PIPES_MASK;
+		tmp = r6xx_remap_render_backend(rdev, tmp,
+						rdev->config.cayman.max_backends_per_se *
+						rdev->config.cayman.max_shader_engines,
+						CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+	}
 	WREG32(GB_BACKEND_MAP, tmp);
 
 	cgts_tcc_disable = 0xffff0000;
@@ -1618,6 +1642,7 @@ int cayman_resume(struct radeon_device *
 int cayman_suspend(struct radeon_device *rdev)
 {
 	r600_audio_fini(rdev);
+	radeon_vm_manager_fini(rdev);
 	cayman_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);
 	evergreen_irq_suspend(rdev);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/nid.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/nid.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/nid.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/nid.h	2013-05-11 16:57:46.000000000 -0400
@@ -45,6 +45,10 @@
 #define ARUBA_GB_ADDR_CONFIG_GOLDEN        0x12010001
 
 #define DMIF_ADDR_CONFIG  				0xBD4
+
+/* DCE6 only */
+#define DMIF_ADDR_CALC  				0xC00
+
 #define	SRBM_GFX_CNTL				        0x0E44
 #define		RINGID(x)					(((x) & 0x3) << 0)
 #define		VMID(x)						(((x) & 0x7) << 0)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/r100.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/r100.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/r100.c	2013-05-01 16:38:00.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/r100.c	2013-05-11 19:13:57.000000000 -0400
@@ -63,6 +63,38 @@
  * and others in some cases.
  */
 
+static bool r100_is_in_vblank(struct radeon_device *rdev, int crtc)
+{
+	if (crtc == 0) {
+		if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)
+			return true;
+		else
+			return false;
+	} else {
+		if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)
+			return true;
+		else
+			return false;
+	}
+}
+
+static bool r100_is_counter_moving(struct radeon_device *rdev, int crtc)
+{
+	u32 vline1, vline2;
+
+	if (crtc == 0) {
+		vline1 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+		vline2 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+	} else {
+		vline1 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+		vline2 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+	}
+	if (vline1 != vline2)
+		return true;
+	else
+		return false;
+}
+
 /**
  * r100_wait_for_vblank - vblank wait asic callback.
  *
@@ -73,36 +105,33 @@
  */
 void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
 {
-	int i;
+	unsigned i = 0;
 
 	if (crtc >= rdev->num_crtc)
 		return;
 
 	if (crtc == 0) {
-		if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) {
-			for (i = 0; i < rdev->usec_timeout; i++) {
-				if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR))
-					break;
-				udelay(1);
-			}
-			for (i = 0; i < rdev->usec_timeout; i++) {
-				if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)
-					break;
-				udelay(1);
-			}
-		}
+		if (!(RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN))
+			return;
 	} else {
-		if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) {
-			for (i = 0; i < rdev->usec_timeout; i++) {
-				if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR))
-					break;
-				udelay(1);
-			}
-			for (i = 0; i < rdev->usec_timeout; i++) {
-				if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)
-					break;
-				udelay(1);
-			}
+		if (!(RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN))
+			return;
+	}
+
+	/* depending on when we hit vblank, we may be close to active; if so,
+	 * wait for another frame.
+	 */
+	while (r100_is_in_vblank(rdev, crtc)) {
+		if (i++ % 100 == 0) {
+			if (!r100_is_counter_moving(rdev, crtc))
+				break;
+		}
+	}
+
+	while (!r100_is_in_vblank(rdev, crtc)) {
+		if (i++ % 100 == 0) {
+			if (!r100_is_counter_moving(rdev, crtc))
+				break;
 		}
 	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/r500_reg.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/r500_reg.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/r500_reg.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/r500_reg.h	2013-05-11 16:57:46.000000000 -0400
@@ -357,7 +357,9 @@
 #define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
 #define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4
 
+#define AVIVO_D1MODE_MASTER_UPDATE_LOCK                         0x60e0
 #define AVIVO_D1MODE_MASTER_UPDATE_MODE                         0x60e4
+#define AVIVO_D1CRTC_UPDATE_LOCK                                0x60e8
 
 /* master controls */
 #define AVIVO_DC_CRTC_MASTER_EN                                 0x60f8
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/r600_hdmi.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/r600_hdmi.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/r600_hdmi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/r600_hdmi.c	2013-05-11 16:57:46.000000000 -0400
@@ -489,7 +489,7 @@ void r600_hdmi_enable(struct drm_encoder
 	offset = dig->afmt->offset;
 
 	/* Older chipsets require setting HDMI and routing manually */
-	if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
+	if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) {
 		hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE;
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -544,7 +544,6 @@ void r600_hdmi_disable(struct drm_encode
 
 	/* Called for ATOM_ENCODER_MODE_HDMI only */
 	if (!dig || !dig->afmt) {
-		WARN_ON(1);
 		return;
 	}
 	if (!dig->afmt->enabled)
@@ -558,7 +557,7 @@ void r600_hdmi_disable(struct drm_encode
 	radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
 
 	/* Older chipsets not handled by AtomBIOS */
-	if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
+	if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) {
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
 			WREG32_P(AVIVO_TMDSA_CNTL, 0,
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2013-05-11 16:57:46.000000000 -0400
@@ -2028,6 +2028,8 @@ static int radeon_atombios_parse_power_t
 	num_modes = power_info->info.ucNumOfPowerModeEntries;
 	if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
 		num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
+	if (num_modes == 0)
+		return state_index;
 	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL);
 	if (!rdev->pm.power_state)
 		return state_index;
@@ -2432,6 +2434,8 @@ static int radeon_atombios_parse_power_t
 	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
 
 	radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
+	if (power_info->pplib.ucNumStates == 0)
+		return state_index;
 	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
 				       power_info->pplib.ucNumStates, GFP_KERNEL);
 	if (!rdev->pm.power_state)
@@ -2514,6 +2518,7 @@ static int radeon_atombios_parse_power_t
 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
         u16 data_offset;
 	u8 frev, crev;
+	u8 *power_state_offset;
 
 	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
 				   &frev, &crev, &data_offset))
@@ -2530,15 +2535,17 @@ static int radeon_atombios_parse_power_t
 	non_clock_info_array = (struct _NonClockInfoArray *)
 		(mode_info->atom_context->bios + data_offset +
 		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
+	if (state_array->ucNumEntries == 0)
+		return state_index;
 	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
 				       state_array->ucNumEntries, GFP_KERNEL);
 	if (!rdev->pm.power_state)
 		return state_index;
+	power_state_offset = (u8 *)state_array->states;
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		mode_index = 0;
-		power_state = (union pplib_power_state *)&state_array->states[i];
-		/* XXX this might be an inagua bug... */
-		non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
+		power_state = (union pplib_power_state *)power_state_offset;
+		non_clock_array_index = power_state->v2.nonClockInfoIndex;
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
 		rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
@@ -2550,9 +2557,6 @@ static int radeon_atombios_parse_power_t
 		if (power_state->v2.ucNumDPMLevels) {
 			for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
 				clock_array_index = power_state->v2.clockInfoIndex[j];
-				/* XXX this might be an inagua bug... */
-				if (clock_array_index >= clock_info_array->ucNumEntries)
-					continue;
 				clock_info = (union pplib_clock_info *)
 					&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
 				valid = radeon_atombios_parse_pplib_clock_info(rdev,
@@ -2574,6 +2578,7 @@ static int radeon_atombios_parse_power_t
 								   non_clock_info);
 			state_index++;
 		}
+		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
 	}
 	/* if multiple clock modes, mark the lowest as no display */
 	for (i = 0; i < state_index; i++) {
@@ -2620,7 +2625,9 @@ void radeon_atombios_get_power_modes(str
 		default:
 			break;
 		}
-	} else {
+	}
+
+	if (state_index == 0) {
 		rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
 		if (rdev->pm.power_state) {
 			rdev->pm.power_state[0].clock_info =
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_atpx_handler.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_atpx_handler.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_atpx_handler.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_atpx_handler.c	2013-05-11 16:57:46.000000000 -0400
@@ -43,6 +43,12 @@ struct atpx_verify_interface {
 	u32 function_bits;	/* supported functions bit vector */
 } __packed;
 
+struct atpx_px_params {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u32 valid_flags;	/* which flags are valid */
+	u32 flags;		/* flags */
+} __packed;
+
 struct atpx_power_control {
 	u16 size;
 	u8 dgpu_state;
@@ -123,9 +129,61 @@ static void radeon_atpx_parse_functions(
 }
 
 /**
+ * radeon_atpx_validate_functions - validate ATPX functions
+ *
+ * @atpx: radeon atpx struct
+ *
+ * Validate that required functions are enabled (all asics).
+ * returns 0 on success, error on failure.
+ */
+static int radeon_atpx_validate(struct radeon_atpx *atpx)
+{
+	/* make sure required functions are enabled */
+	/* dGPU power control is required */
+	atpx->functions.power_cntl = true;
+
+	if (atpx->functions.px_params) {
+		union acpi_object *info;
+		struct atpx_px_params output;
+		size_t size;
+		u32 valid_bits;
+
+		info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
+		if (!info)
+			return -EIO;
+
+		memset(&output, 0, sizeof(output));
+
+		size = *(u16 *) info->buffer.pointer;
+		if (size < 10) {
+			printk("ATPX buffer is too small: %zu\n", size);
+			kfree(info);
+			return -EINVAL;
+		}
+		size = min(sizeof(output), size);
+
+		memcpy(&output, info->buffer.pointer, size);
+
+		valid_bits = output.flags & output.valid_flags;
+		/* if separate mux flag is set, mux controls are required */
+		if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
+			atpx->functions.i2c_mux_cntl = true;
+			atpx->functions.disp_mux_cntl = true;
+		}
+		/* if any outputs are muxed, mux controls are required */
+		if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
+				  ATPX_TV_SIGNAL_MUXED |
+				  ATPX_DFP_SIGNAL_MUXED))
+			atpx->functions.disp_mux_cntl = true;
+
+		kfree(info);
+	}
+	return 0;
+}
+
+/**
  * radeon_atpx_verify_interface - verify ATPX
  *
- * @handle: acpi handle
  * @atpx: radeon atpx struct
  *
  * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
@@ -406,8 +464,19 @@ static bool radeon_atpx_pci_probe_handle
  */
 static int radeon_atpx_init(void)
 {
+	int r;
+
 	/* set up the ATPX handle */
-	return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx);
+	r = radeon_atpx_verify_interface(&radeon_atpx_priv.atpx);
+	if (r)
+		return r;
+
+	/* validate the atpx setup */
+	r = radeon_atpx_validate(&radeon_atpx_priv.atpx);
+	if (r)
+		return r;
+
+	return 0;
 }
 
 /**
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_benchmark.c	2013-05-11 16:57:46.000000000 -0400
@@ -135,13 +135,15 @@ static void radeon_benchmark_move(struct
 						     sdomain, ddomain, "dma");
 	}
 
-	time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
-					RADEON_BENCHMARK_COPY_BLIT, n);
-	if (time < 0)
-		goto out_cleanup;
-	if (time > 0)
-		radeon_benchmark_log_results(n, size, time,
-					     sdomain, ddomain, "blit");
+	if (rdev->asic->copy.blit) {
+		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+						RADEON_BENCHMARK_COPY_BLIT, n);
+		if (time < 0)
+			goto out_cleanup;
+		if (time > 0)
+			radeon_benchmark_log_results(n, size, time,
+						     sdomain, ddomain, "blit");
+	}
 
 out_cleanup:
 	if (sobj) {
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_combios.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_combios.c	2013-05-11 16:57:46.000000000 -0400
@@ -970,6 +970,15 @@ struct radeon_encoder_primary_dac *radeo
 			found = 1;
 	}
 
+	/* quirks */
+	/* Radeon 9100 (R200) */
+	if ((dev->pdev->device == 0x514D) &&
+	    (dev->pdev->subsystem_vendor == 0x174B) &&
+	    (dev->pdev->subsystem_device == 0x7149)) {
+		/* vbios value is bad, use the default */
+		found = 0;
+	}
+
 	if (!found) /* fallback to defaults */
 		radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
 
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c	2013-05-11 16:57:46.000000000 -0400
@@ -400,6 +400,9 @@ void radeon_irq_kms_enable_afmt(struct r
 {
 	unsigned long irqflags;
 
+	if (!rdev->ddev->irq_enabled)
+		return;
+
 	spin_lock_irqsave(&rdev->irq.lock, irqflags);
 	rdev->irq.afmt[block] = true;
 	radeon_irq_set(rdev);
@@ -419,6 +422,9 @@ void radeon_irq_kms_disable_afmt(struct
 {
 	unsigned long irqflags;
 
+	if (!rdev->ddev->irq_enabled)
+		return;
+
 	spin_lock_irqsave(&rdev->irq.lock, irqflags);
 	rdev->irq.afmt[block] = false;
 	radeon_irq_set(rdev);
@@ -438,6 +444,9 @@ void radeon_irq_kms_enable_hpd(struct ra
 	unsigned long irqflags;
 	int i;
 
+	if (!rdev->ddev->irq_enabled)
+		return;
+
 	spin_lock_irqsave(&rdev->irq.lock, irqflags);
 	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
 		rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
@@ -458,6 +467,9 @@ void radeon_irq_kms_disable_hpd(struct r
 	unsigned long irqflags;
 	int i;
 
+	if (!rdev->ddev->irq_enabled)
+		return;
+
 	spin_lock_irqsave(&rdev->irq.lock, irqflags);
 	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
 		rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_kms.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_kms.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_kms.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_kms.c	2013-05-11 16:57:46.000000000 -0400
@@ -50,9 +50,13 @@ int radeon_driver_unload_kms(struct drm_
 
 	if (rdev == NULL)
 		return 0;
+	if (rdev->rmmio == NULL)
+		goto done_free;
 	radeon_acpi_fini(rdev);
 	radeon_modeset_fini(rdev);
 	radeon_device_fini(rdev);
+
+done_free:
 	kfree(rdev);
 	dev->dev_private = NULL;
 	return 0;
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_pm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_pm.c	2013-05-11 16:57:46.000000000 -0400
@@ -169,7 +169,7 @@ static void radeon_set_power_state(struc
 
 		/* starting with BTC, there is one state that is used for both
 		 * MH and SH.  Difference is that we always use the high clock index for
-		 * mclk.
+		 * mclk and vddci.
 		 */
 		if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
 		    (rdev->family >= CHIP_BARTS) &&
@@ -843,7 +843,11 @@ static int radeon_debugfs_pm_info(struct
 	struct radeon_device *rdev = dev->dev_private;
 
 	seq_printf(m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk);
-	seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
+	/* radeon_get_engine_clock is not reliable on APUs so just print the current clock */
+	if ((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP))
+		seq_printf(m, "current engine clock: %u0 kHz\n", rdev->pm.current_sclk);
+	else
+		seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
 	seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk);
 	if (rdev->asic->pm.get_memory_clock)
 		seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/radeon_ring.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/radeon_ring.c	2013-05-11 16:57:46.000000000 -0400
@@ -161,7 +161,8 @@ int radeon_ib_schedule(struct radeon_dev
 		radeon_semaphore_free(rdev, &ib->semaphore, NULL);
 	}
 	/* if we can't remember our last VM flush then flush now! */
-	if (ib->vm && !ib->vm->last_flush) {
+	/* XXX figure out why we have to flush for every IB */
+	if (ib->vm /*&& !ib->vm->last_flush*/) {
 		radeon_ring_vm_flush(rdev, ib->ring, ib->vm);
 	}
 	if (const_ib) {
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/rs600.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/rs600.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/rs600.c	2013-05-11 16:57:46.000000000 -0400
@@ -52,23 +52,59 @@ static const u32 crtc_offsets[2] =
 	AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
 };
 
+static bool avivo_is_in_vblank(struct radeon_device *rdev, int crtc)
+{
+	if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)
+		return true;
+	else
+		return false;
+}
+
+static bool avivo_is_counter_moving(struct radeon_device *rdev, int crtc)
+{
+	u32 pos1, pos2;
+
+	pos1 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+	pos2 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+	if (pos1 != pos2)
+		return true;
+	else
+		return false;
+}
+
+/**
+ * avivo_wait_for_vblank - vblank wait asic callback.
+ *
+ * @rdev: radeon_device pointer
+ * @crtc: crtc to wait for vblank on
+ *
+ * Wait for vblank on the requested crtc (r5xx-r7xx).
+ */
 void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
 {
-	int i;
+	unsigned i = 0;
 
 	if (crtc >= rdev->num_crtc)
 		return;
 
-	if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN) {
-		for (i = 0; i < rdev->usec_timeout; i++) {
-			if (!(RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK))
+	if (!(RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN))
+		return;
+
+	/* depending on when we hit vblank, we may be close to active; if so,
+	 * wait for another frame.
+	 */
+	while (avivo_is_in_vblank(rdev, crtc)) {
+		if (i++ % 100 == 0) {
+			if (!avivo_is_counter_moving(rdev, crtc))
 				break;
-			udelay(1);
 		}
-		for (i = 0; i < rdev->usec_timeout; i++) {
-			if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)
+	}
+
+	while (!avivo_is_in_vblank(rdev, crtc)) {
+		if (i++ % 100 == 0) {
+			if (!avivo_is_counter_moving(rdev, crtc))
 				break;
-			udelay(1);
 		}
 	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/rv515.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/rv515.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/rv515.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/rv515.c	2013-05-11 16:57:46.000000000 -0400
@@ -303,8 +303,10 @@ void rv515_mc_stop(struct radeon_device
 			tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
 			if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) {
 				radeon_wait_for_vblank(rdev, i);
+				WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
 				tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
 				WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+				WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
 			}
 			/* wait for the next frame */
 			frame_count = radeon_get_vblank_counter(rdev, i);
@@ -313,6 +315,15 @@ void rv515_mc_stop(struct radeon_device
 					break;
 				udelay(1);
 			}
+
+			/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+			WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
+			tmp &= ~AVIVO_CRTC_EN;
+			WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+			WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			save->crtc_enabled[i] = false;
+			/* ***** */
 		} else {
 			save->crtc_enabled[i] = false;
 		}
@@ -338,6 +349,22 @@ void rv515_mc_stop(struct radeon_device
 	}
 	/* wait for the MC to settle */
 	udelay(100);
+
+	/* lock double buffered regs */
+	for (i = 0; i < rdev->num_crtc; i++) {
+		if (save->crtc_enabled[i]) {
+			tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+			if (!(tmp & AVIVO_D1GRPH_UPDATE_LOCK)) {
+				tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
+				WREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (!(tmp & 1)) {
+				tmp |= 1;
+				WREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+		}
+	}
 }
 
 void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
@@ -348,7 +375,7 @@ void rv515_mc_resume(struct radeon_devic
 	/* update crtc base addresses */
 	for (i = 0; i < rdev->num_crtc; i++) {
 		if (rdev->family >= CHIP_RV770) {
-			if (i == 1) {
+			if (i == 0) {
 				WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
 				       upper_32_bits(rdev->mc.vram_start));
 				WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
@@ -367,6 +394,33 @@ void rv515_mc_resume(struct radeon_devic
 	}
 	WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
 
+	/* unlock regs and wait for update */
+	for (i = 0; i < rdev->num_crtc; i++) {
+		if (save->crtc_enabled[i]) {
+			tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i]);
+			if ((tmp & 0x3) != 0) {
+				tmp &= ~0x3;
+				WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+			if (tmp & AVIVO_D1GRPH_UPDATE_LOCK) {
+				tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
+				WREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (tmp & 1) {
+				tmp &= ~1;
+				WREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+			for (j = 0; j < rdev->usec_timeout; j++) {
+				tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+				if ((tmp & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) == 0)
+					break;
+				udelay(1);
+			}
+		}
+	}
+
 	if (rdev->family >= CHIP_R600) {
 		/* unblackout the MC */
 		if (rdev->family >= CHIP_RV770)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/si.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/si.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/si.c	2013-05-01 16:38:13.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/si.c	2013-05-11 19:14:10.000000000 -0400
@@ -1360,7 +1360,7 @@ static void si_select_se_sh(struct radeo
 	u32 data = INSTANCE_BROADCAST_WRITES;
 
 	if ((se_num == 0xffffffff) && (sh_num == 0xffffffff))
-		data = SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
+		data |= SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
 	else if (se_num == 0xffffffff)
 		data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num);
 	else if (sh_num == 0xffffffff)
@@ -1645,6 +1645,7 @@ static void si_gpu_init(struct radeon_de
 
 	WREG32(GB_ADDR_CONFIG, gb_addr_config);
 	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
+	WREG32(DMIF_ADDR_CALC, gb_addr_config);
 	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
 	WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
 	WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
@@ -4218,6 +4219,7 @@ int si_resume(struct radeon_device *rdev
 
 int si_suspend(struct radeon_device *rdev)
 {
+	radeon_vm_manager_fini(rdev);
 	si_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);
 	si_irq_suspend(rdev);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/sid.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/sid.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/radeon/sid.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/radeon/sid.h	2013-05-11 16:57:46.000000000 -0400
@@ -60,6 +60,8 @@
 
 #define DMIF_ADDR_CONFIG  				0xBD4
 
+#define DMIF_ADDR_CALC  				0xC00
+
 #define	SRBM_STATUS				        0xE50
 
 #define	SRBM_SOFT_RESET				        0x0E60
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/udl/udl_connector.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/udl/udl_connector.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/udl/udl_connector.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/udl/udl_connector.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,6 +61,10 @@ static int udl_get_modes(struct drm_conn
 	int ret;
 
 	edid = (struct edid *)udl_get_edid(udl);
+	if (!edid) {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		return 0;
+	}
 
 	/*
 	 * We only read the main block, but if the monitor reports extension
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/udl/udl_drv.h linux-libre-3.8.13-gnu1/drivers/gpu/drm/udl/udl_drv.h
--- linux-libre-3.8-gnu1/drivers/gpu/drm/udl/udl_drv.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/udl/udl_drv.h	2013-05-11 16:57:46.000000000 -0400
@@ -75,6 +75,8 @@ struct udl_framebuffer {
 	struct drm_framebuffer base;
 	struct udl_gem_object *obj;
 	bool active_16; /* active on the 16-bit channel */
+	int x1, y1, x2, y2; /* dirty rect */
+	spinlock_t dirty_lock;
 };
 
 #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base)
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/drm/udl/udl_fb.c linux-libre-3.8.13-gnu1/drivers/gpu/drm/udl/udl_fb.c
--- linux-libre-3.8-gnu1/drivers/gpu/drm/udl/udl_fb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/drm/udl/udl_fb.c	2013-05-11 16:57:46.000000000 -0400
@@ -22,9 +22,9 @@
 
 #include <drm/drm_fb_helper.h>
 
-#define DL_DEFIO_WRITE_DELAY    5 /* fb_deferred_io.delay in jiffies */
+#define DL_DEFIO_WRITE_DELAY    (HZ/20) /* fb_deferred_io.delay in jiffies */
 
-static int fb_defio = 1;  /* Optionally enable experimental fb_defio mmap support */
+static int fb_defio = 0;  /* Optionally enable experimental fb_defio mmap support */
 static int fb_bpp = 16;
 
 module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
@@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebu
 	struct urb *urb;
 	int aligned_x;
 	int bpp = (fb->base.bits_per_pixel / 8);
+	int x2, y2;
+	bool store_for_later = false;
+	unsigned long flags;
 
 	if (!fb->active_16)
 		return 0;
@@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebu
 		}
 	}
 
-	start_cycles = get_cycles();
-
 	aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
 	width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
 	x = aligned_x;
@@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebu
 	    (y + height > fb->base.height))
 		return -EINVAL;
 
+	/* if we are in atomic just store the info
+	   can't test inside spin lock */
+	if (in_atomic())
+		store_for_later = true;
+
+	x2 = x + width - 1;
+	y2 = y + height - 1;
+
+	spin_lock_irqsave(&fb->dirty_lock, flags);
+
+	if (fb->y1 < y)
+		y = fb->y1;
+	if (fb->y2 > y2)
+		y2 = fb->y2;
+	if (fb->x1 < x)
+		x = fb->x1;
+	if (fb->x2 > x2)
+		x2 = fb->x2;
+
+	if (store_for_later) {
+		fb->x1 = x;
+		fb->x2 = x2;
+		fb->y1 = y;
+		fb->y2 = y2;
+		spin_unlock_irqrestore(&fb->dirty_lock, flags);
+		return 0;
+	}
+
+	fb->x1 = fb->y1 = INT_MAX;
+	fb->x2 = fb->y2 = 0;
+
+	spin_unlock_irqrestore(&fb->dirty_lock, flags);
+	start_cycles = get_cycles();
+
 	urb = udl_get_urb(dev);
 	if (!urb)
 		return 0;
 	cmd = urb->transfer_buffer;
 
-	for (i = y; i < y + height ; i++) {
+	for (i = y; i <= y2 ; i++) {
 		const int line_offset = fb->base.pitches[0] * i;
 		const int byte_offset = line_offset + (x * bpp);
 		const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
 		if (udl_render_hline(dev, bpp, &urb,
 				     (char *) fb->obj->vmapping,
 				     &cmd, byte_offset, dev_byte_offset,
-				     width * bpp,
+				     (x2 - x + 1) * bpp,
 				     &bytes_identical, &bytes_sent))
 			goto error;
 	}
@@ -434,6 +469,7 @@ udl_framebuffer_init(struct drm_device *
 {
 	int ret;
 
+	spin_lock_init(&ufb->dirty_lock);
 	ufb->obj = obj;
 	ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);
 	drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);
diff -druNp linux-libre-3.8-gnu1/drivers/gpu/vga/vga_switcheroo.c linux-libre-3.8.13-gnu1/drivers/gpu/vga/vga_switcheroo.c
--- linux-libre-3.8-gnu1/drivers/gpu/vga/vga_switcheroo.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/gpu/vga/vga_switcheroo.c	2013-05-11 16:57:46.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/fb.h>
 
 #include <linux/pci.h>
+#include <linux/console.h>
 #include <linux/vga_switcheroo.h>
 
 #include <linux/vgaarb.h>
@@ -337,8 +338,10 @@ static int vga_switchto_stage2(struct vg
 
 	if (new_client->fb_info) {
 		struct fb_event event;
+		console_lock();
 		event.info = new_client->fb_info;
 		fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
+		console_unlock();
 	}
 
 	ret = vgasr_priv.handler->switchto(new_client->id);
diff -druNp linux-libre-3.8-gnu1/drivers/hid/hid-core.c linux-libre-3.8.13-gnu1/drivers/hid/hid-core.c
--- linux-libre-3.8-gnu1/drivers/hid/hid-core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/hid-core.c	2013-05-11 16:57:46.000000000 -0400
@@ -1697,6 +1697,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
@@ -2070,6 +2071,7 @@ static const struct hid_device_id hid_ig
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
diff -druNp linux-libre-3.8-gnu1/drivers/hid/hid-ids.h linux-libre-3.8.13-gnu1/drivers/hid/hid-ids.h
--- linux-libre-3.8-gnu1/drivers/hid/hid-ids.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/hid-ids.h	2013-05-11 16:57:46.000000000 -0400
@@ -554,6 +554,9 @@
 #define USB_VENDOR_ID_MADCATZ		0x0738
 #define USB_DEVICE_ID_MADCATZ_BEATPAD	0x4540
 
+#define USB_VENDOR_ID_MASTERKIT			0x16c0
+#define USB_DEVICE_ID_MASTERKIT_MA901RADIO	0x05df
+
 #define USB_VENDOR_ID_MCC		0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
@@ -584,6 +587,9 @@
 #define USB_VENDOR_ID_MONTEREY		0x0566
 #define USB_DEVICE_ID_GENIUS_KB29E	0x3004
 
+#define USB_VENDOR_ID_MSI		0x1770
+#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL	0xff00
+
 #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
 #define USB_DEVICE_ID_N_S_HARMONY	0xc359
 
@@ -675,6 +681,9 @@
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001		0x3001
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008		0x3008
 
+#define USB_VENDOR_ID_REALTEK		0x0bda
+#define USB_DEVICE_ID_REALTEK_READER	0x0152
+
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
 #define USB_DEVICE_ID_ROCCAT_ARVO	0x30d4
 #define USB_DEVICE_ID_ROCCAT_ISKU	0x319c
@@ -709,6 +718,7 @@
 
 #define USB_VENDOR_ID_SONY			0x054c
 #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE	0x024b
+#define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE	0x0374
 #define USB_DEVICE_ID_SONY_PS3_BDREMOTE		0x0306
 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER	0x042f
diff -druNp linux-libre-3.8-gnu1/drivers/hid/hid-logitech-dj.c linux-libre-3.8.13-gnu1/drivers/hid/hid-logitech-dj.c
--- linux-libre-3.8-gnu1/drivers/hid/hid-logitech-dj.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/hid-logitech-dj.c	2013-05-11 16:57:46.000000000 -0400
@@ -459,19 +459,25 @@ static int logi_dj_recv_send_report(stru
 				    struct dj_report *dj_report)
 {
 	struct hid_device *hdev = djrcv_dev->hdev;
-	int sent_bytes;
+	struct hid_report *report;
+	struct hid_report_enum *output_report_enum;
+	u8 *data = (u8 *)(&dj_report->device_index);
+	int i;
 
-	if (!hdev->hid_output_raw_report) {
-		dev_err(&hdev->dev, "%s:"
-			"hid_output_raw_report is null\n", __func__);
+	output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
+	report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+
+	if (!report) {
+		dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
 		return -ENODEV;
 	}
 
-	sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
-						 sizeof(struct dj_report),
-						 HID_OUTPUT_REPORT);
+	for (i = 0; i < report->field[0]->report_count; i++)
+		report->field[0]->value[i] = data[i];
 
-	return (sent_bytes < 0) ? sent_bytes : 0;
+	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+
+	return 0;
 }
 
 static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
diff -druNp linux-libre-3.8-gnu1/drivers/hid/hid-magicmouse.c linux-libre-3.8.13-gnu1/drivers/hid/hid-magicmouse.c
--- linux-libre-3.8-gnu1/drivers/hid/hid-magicmouse.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/hid-magicmouse.c	2013-05-11 16:57:46.000000000 -0400
@@ -462,6 +462,21 @@ static int magicmouse_input_mapping(stru
 	return 0;
 }
 
+static void magicmouse_input_configured(struct hid_device *hdev,
+		struct hid_input *hi)
+
+{
+	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+
+	int ret = magicmouse_setup_input(msc->input, hdev);
+	if (ret) {
+		hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
+		/* clean msc->input to notify probe() of the failure */
+		msc->input = NULL;
+	}
+}
+
+
 static int magicmouse_probe(struct hid_device *hdev,
 	const struct hid_device_id *id)
 {
@@ -493,15 +508,10 @@ static int magicmouse_probe(struct hid_d
 		goto err_free;
 	}
 
-	/* We do this after hid-input is done parsing reports so that
-	 * hid-input uses the most natural button and axis IDs.
-	 */
-	if (msc->input) {
-		ret = magicmouse_setup_input(msc->input, hdev);
-		if (ret) {
-			hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
-			goto err_stop_hw;
-		}
+	if (!msc->input) {
+		hid_err(hdev, "magicmouse input not registered\n");
+		ret = -ENOMEM;
+		goto err_stop_hw;
 	}
 
 	if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
@@ -568,6 +578,7 @@ static struct hid_driver magicmouse_driv
 	.remove = magicmouse_remove,
 	.raw_event = magicmouse_raw_event,
 	.input_mapping = magicmouse_input_mapping,
+	.input_configured = magicmouse_input_configured,
 };
 
 static int __init magicmouse_init(void)
diff -druNp linux-libre-3.8-gnu1/drivers/hid/hid-sony.c linux-libre-3.8.13-gnu1/drivers/hid/hid-sony.c
--- linux-libre-3.8-gnu1/drivers/hid/hid-sony.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/hid-sony.c	2013-05-11 16:57:46.000000000 -0400
@@ -43,9 +43,19 @@ static __u8 *sony_report_fixup(struct hi
 {
 	struct sony_sc *sc = hid_get_drvdata(hdev);
 
-	if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
-			*rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
-		hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
+	/*
+	 * Some Sony RF receivers wrongly declare the mouse pointer as a
+	 * a constant non-data variable.
+	 */
+	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
+	    /* usage page: generic desktop controls */
+	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
+	    /* usage: mouse */
+	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
+	    /* input (usage page for x,y axes): constant, variable, relative */
+	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
+		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
+		/* input: data, variable, relative */
 		rdesc[55] = 0x06;
 	}
 
@@ -217,6 +227,8 @@ static const struct hid_device_id sony_d
 		.driver_data = SIXAXIS_CONTROLLER_BT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
 		.driver_data = VAIO_RDESC_CONSTANT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
+		.driver_data = VAIO_RDESC_CONSTANT },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, sony_devices);
diff -druNp linux-libre-3.8-gnu1/drivers/hid/hid-wiimote-ext.c linux-libre-3.8.13-gnu1/drivers/hid/hid-wiimote-ext.c
--- linux-libre-3.8-gnu1/drivers/hid/hid-wiimote-ext.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/hid-wiimote-ext.c	2013-05-11 16:57:46.000000000 -0400
@@ -403,14 +403,14 @@ static void handler_nunchuck(struct wiim
 
 	if (ext->motionp) {
 		input_report_key(ext->input,
-			wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04));
+			wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x04));
 		input_report_key(ext->input,
-			wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08));
+			wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x08));
 	} else {
 		input_report_key(ext->input,
-			wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01));
+			wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x01));
 		input_report_key(ext->input,
-			wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02));
+			wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x02));
 	}
 
 	input_sync(ext->input);
diff -druNp linux-libre-3.8-gnu1/drivers/hid/usbhid/hid-quirks.c linux-libre-3.8.13-gnu1/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-3.8-gnu1/drivers/hid/usbhid/hid-quirks.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hid/usbhid/hid-quirks.c	2013-05-11 16:57:46.000000000 -0400
@@ -73,6 +73,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
@@ -80,6 +81,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
diff -druNp linux-libre-3.8-gnu1/drivers/hwmon/lineage-pem.c linux-libre-3.8.13-gnu1/drivers/hwmon/lineage-pem.c
--- linux-libre-3.8-gnu1/drivers/hwmon/lineage-pem.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hwmon/lineage-pem.c	2013-05-11 16:57:46.000000000 -0400
@@ -422,6 +422,7 @@ static struct attribute *pem_input_attri
 	&sensor_dev_attr_in2_input.dev_attr.attr,
 	&sensor_dev_attr_curr1_input.dev_attr.attr,
 	&sensor_dev_attr_power1_input.dev_attr.attr,
+	NULL
 };
 
 static const struct attribute_group pem_input_group = {
@@ -432,6 +433,7 @@ static struct attribute *pem_fan_attribu
 	&sensor_dev_attr_fan1_input.dev_attr.attr,
 	&sensor_dev_attr_fan2_input.dev_attr.attr,
 	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	NULL
 };
 
 static const struct attribute_group pem_fan_group = {
diff -druNp linux-libre-3.8-gnu1/drivers/hwmon/pmbus/ltc2978.c linux-libre-3.8.13-gnu1/drivers/hwmon/pmbus/ltc2978.c
--- linux-libre-3.8-gnu1/drivers/hwmon/pmbus/ltc2978.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hwmon/pmbus/ltc2978.c	2013-05-11 16:57:46.000000000 -0400
@@ -59,10 +59,10 @@ enum chips { ltc2978, ltc3880 };
 struct ltc2978_data {
 	enum chips id;
 	int vin_min, vin_max;
-	int temp_min, temp_max;
+	int temp_min, temp_max[2];
 	int vout_min[8], vout_max[8];
 	int iout_max[2];
-	int temp2_max[2];
+	int temp2_max;
 	struct pmbus_driver_info info;
 };
 
@@ -113,9 +113,10 @@ static int ltc2978_read_word_data_common
 		ret = pmbus_read_word_data(client, page,
 					   LTC2978_MFR_TEMPERATURE_PEAK);
 		if (ret >= 0) {
-			if (lin11_to_val(ret) > lin11_to_val(data->temp_max))
-				data->temp_max = ret;
-			ret = data->temp_max;
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->temp_max[page]))
+				data->temp_max[page] = ret;
+			ret = data->temp_max[page];
 		}
 		break;
 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
@@ -204,10 +205,9 @@ static int ltc3880_read_word_data(struct
 		ret = pmbus_read_word_data(client, page,
 					   LTC3880_MFR_TEMPERATURE2_PEAK);
 		if (ret >= 0) {
-			if (lin11_to_val(ret)
-			    > lin11_to_val(data->temp2_max[page]))
-				data->temp2_max[page] = ret;
-			ret = data->temp2_max[page];
+			if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
+				data->temp2_max = ret;
+			ret = data->temp2_max;
 		}
 		break;
 	case PMBUS_VIRT_READ_VIN_MIN:
@@ -248,11 +248,11 @@ static int ltc2978_write_word_data(struc
 
 	switch (reg) {
 	case PMBUS_VIRT_RESET_IOUT_HISTORY:
-		data->iout_max[page] = 0x7fff;
+		data->iout_max[page] = 0x7c00;
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
 	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
-		data->temp2_max[page] = 0x7fff;
+		data->temp2_max = 0x7c00;
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
@@ -262,12 +262,12 @@ static int ltc2978_write_word_data(struc
 		break;
 	case PMBUS_VIRT_RESET_VIN_HISTORY:
 		data->vin_min = 0x7bff;
-		data->vin_max = 0;
+		data->vin_max = 0x7c00;
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
 	case PMBUS_VIRT_RESET_TEMP_HISTORY:
 		data->temp_min = 0x7bff;
-		data->temp_max = 0x7fff;
+		data->temp_max[page] = 0x7c00;
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
 	default:
@@ -321,12 +321,14 @@ static int ltc2978_probe(struct i2c_clie
 	info = &data->info;
 	info->write_word_data = ltc2978_write_word_data;
 
-	data->vout_min[0] = 0xffff;
 	data->vin_min = 0x7bff;
+	data->vin_max = 0x7c00;
 	data->temp_min = 0x7bff;
-	data->temp_max = 0x7fff;
+	for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
+		data->temp_max[i] = 0x7c00;
+	data->temp2_max = 0x7c00;
 
-	switch (id->driver_data) {
+	switch (data->id) {
 	case ltc2978:
 		info->read_word_data = ltc2978_read_word_data;
 		info->pages = 8;
@@ -336,7 +338,6 @@ static int ltc2978_probe(struct i2c_clie
 		for (i = 1; i < 8; i++) {
 			info->func[i] = PMBUS_HAVE_VOUT
 			  | PMBUS_HAVE_STATUS_VOUT;
-			data->vout_min[i] = 0xffff;
 		}
 		break;
 	case ltc3880:
@@ -352,11 +353,14 @@ static int ltc2978_probe(struct i2c_clie
 		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
 		  | PMBUS_HAVE_POUT
 		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
-		data->vout_min[1] = 0xffff;
+		data->iout_max[0] = 0x7c00;
+		data->iout_max[1] = 0x7c00;
 		break;
 	default:
 		return -ENODEV;
 	}
+	for (i = 0; i < info->pages; i++)
+		data->vout_min[i] = 0xffff;
 
 	return pmbus_do_probe(client, id, info);
 }
diff -druNp linux-libre-3.8-gnu1/drivers/hwmon/sht15.c linux-libre-3.8.13-gnu1/drivers/hwmon/sht15.c
--- linux-libre-3.8-gnu1/drivers/hwmon/sht15.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hwmon/sht15.c	2013-05-11 16:57:46.000000000 -0400
@@ -926,7 +926,13 @@ static int sht15_probe(struct platform_d
 		if (voltage)
 			data->supply_uV = voltage;
 
-		regulator_enable(data->reg);
+		ret = regulator_enable(data->reg);
+		if (ret != 0) {
+			dev_err(&pdev->dev,
+				"failed to enable regulator: %d\n", ret);
+			return ret;
+		}
+
 		/*
 		 * Setup a notifier block to update this if another device
 		 * causes the voltage to change
diff -druNp linux-libre-3.8-gnu1/drivers/hwspinlock/hwspinlock_core.c linux-libre-3.8.13-gnu1/drivers/hwspinlock/hwspinlock_core.c
--- linux-libre-3.8-gnu1/drivers/hwspinlock/hwspinlock_core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/hwspinlock/hwspinlock_core.c	2013-05-11 16:57:46.000000000 -0400
@@ -416,6 +416,8 @@ static int __hwspin_lock_request(struct
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
 		dev_err(dev, "%s: can't power on device\n", __func__);
+		pm_runtime_put_noidle(dev);
+		module_put(dev->driver->owner);
 		return ret;
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/i2c/busses/i2c-tegra.c linux-libre-3.8.13-gnu1/drivers/i2c/busses/i2c-tegra.c
--- linux-libre-3.8-gnu1/drivers/i2c/busses/i2c-tegra.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/i2c/busses/i2c-tegra.c	2013-05-11 16:57:46.000000000 -0400
@@ -392,7 +392,11 @@ static int tegra_i2c_init(struct tegra_i
 	u32 val;
 	int err = 0;
 
-	tegra_i2c_clock_enable(i2c_dev);
+	err = tegra_i2c_clock_enable(i2c_dev);
+	if (err < 0) {
+		dev_err(i2c_dev->dev, "Clock enable failed %d\n", err);
+		return err;
+	}
 
 	tegra_periph_reset_assert(i2c_dev->div_clk);
 	udelay(2);
@@ -599,7 +603,12 @@ static int tegra_i2c_xfer(struct i2c_ada
 	if (i2c_dev->is_suspended)
 		return -EBUSY;
 
-	tegra_i2c_clock_enable(i2c_dev);
+	ret = tegra_i2c_clock_enable(i2c_dev);
+	if (ret < 0) {
+		dev_err(i2c_dev->dev, "Clock enable failed %d\n", ret);
+		return ret;
+	}
+
 	for (i = 0; i < num; i++) {
 		enum msg_end_type end_type = MSG_END_STOP;
 		if (i < (num - 1)) {
diff -druNp linux-libre-3.8-gnu1/drivers/i2c/busses/i2c-xiic.c linux-libre-3.8.13-gnu1/drivers/i2c/busses/i2c-xiic.c
--- linux-libre-3.8-gnu1/drivers/i2c/busses/i2c-xiic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/i2c/busses/i2c-xiic.c	2013-05-11 16:57:46.000000000 -0400
@@ -312,10 +312,8 @@ static void xiic_fill_tx_fifo(struct xii
 			/* last message in transfer -> STOP */
 			data |= XIIC_TX_DYN_STOP_MASK;
 			dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__);
-
-			xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
-		} else
-			xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data);
+		}
+		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
 	}
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/infiniband/hw/cxgb4/qp.c linux-libre-3.8.13-gnu1/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-3.8-gnu1/drivers/infiniband/hw/cxgb4/qp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/infiniband/hw/cxgb4/qp.c	2013-05-11 16:57:46.000000000 -0400
@@ -100,6 +100,16 @@ static int alloc_host_sq(struct c4iw_rde
 	return 0;
 }
 
+static int alloc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq, int user)
+{
+	int ret = -ENOSYS;
+	if (user)
+		ret = alloc_oc_sq(rdev, sq);
+	if (ret)
+		ret = alloc_host_sq(rdev, sq);
+	return ret;
+}
+
 static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 		      struct c4iw_dev_ucontext *uctx)
 {
@@ -168,18 +178,9 @@ static int create_qp(struct c4iw_rdev *r
 		goto free_sw_rq;
 	}
 
-	if (user) {
-		ret = alloc_oc_sq(rdev, &wq->sq);
-		if (ret)
-			goto free_hwaddr;
-
-		ret = alloc_host_sq(rdev, &wq->sq);
-		if (ret)
-			goto free_sq;
-	} else
-		ret = alloc_host_sq(rdev, &wq->sq);
-		if (ret)
-			goto free_hwaddr;
+	ret = alloc_sq(rdev, &wq->sq, user);
+	if (ret)
+		goto free_hwaddr;
 	memset(wq->sq.queue, 0, wq->sq.memsize);
 	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
 
diff -druNp linux-libre-3.8-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-3.8.13-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-3.8-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2013-05-11 16:57:46.000000000 -0400
@@ -758,9 +758,13 @@ void ipoib_cm_send(struct net_device *de
 		if (++priv->tx_outstanding == ipoib_sendq_size) {
 			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
 				  tx->qp->qp_num);
-			if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
-				ipoib_warn(priv, "request notify on send CQ failed\n");
 			netif_stop_queue(dev);
+			rc = ib_req_notify_cq(priv->send_cq,
+				IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS);
+			if (rc < 0)
+				ipoib_warn(priv, "request notify on send CQ failed\n");
+			else if (rc)
+				ipoib_send_comp_handler(priv->send_cq, dev);
 		}
 	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/infiniband/ulp/srp/ib_srp.c linux-libre-3.8.13-gnu1/drivers/infiniband/ulp/srp/ib_srp.c
--- linux-libre-3.8-gnu1/drivers/infiniband/ulp/srp/ib_srp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/infiniband/ulp/srp/ib_srp.c	2013-05-11 16:57:46.000000000 -0400
@@ -700,23 +700,24 @@ static int srp_reconnect_target(struct s
 	struct Scsi_Host *shost = target->scsi_host;
 	int i, ret;
 
-	if (target->state != SRP_TARGET_LIVE)
-		return -EAGAIN;
-
 	scsi_target_block(&shost->shost_gendev);
 
 	srp_disconnect_target(target);
 	/*
-	 * Now get a new local CM ID so that we avoid confusing the
-	 * target in case things are really fouled up.
+	 * Now get a new local CM ID so that we avoid confusing the target in
+	 * case things are really fouled up. Doing so also ensures that all CM
+	 * callbacks will have finished before a new QP is allocated.
 	 */
 	ret = srp_new_cm_id(target);
-	if (ret)
-		goto unblock;
-
-	ret = srp_create_target_ib(target);
-	if (ret)
-		goto unblock;
+	/*
+	 * Whether or not creating a new CM ID succeeded, create a new
+	 * QP. This guarantees that all completion callback function
+	 * invocations have finished before request resetting starts.
+	 */
+	if (ret == 0)
+		ret = srp_create_target_ib(target);
+	else
+		srp_create_target_ib(target);
 
 	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
 		struct srp_request *req = &target->req_ring[i];
@@ -728,11 +729,12 @@ static int srp_reconnect_target(struct s
 	for (i = 0; i < SRP_SQ_SIZE; ++i)
 		list_add(&target->tx_ring[i]->list, &target->free_tx);
 
-	ret = srp_connect_target(target);
+	if (ret == 0)
+		ret = srp_connect_target(target);
 
-unblock:
 	scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING :
 			    SDEV_TRANSPORT_OFFLINE);
+	target->transport_offline = !!ret;
 
 	if (ret)
 		goto err;
@@ -1352,6 +1354,12 @@ static int srp_queuecommand(struct Scsi_
 	unsigned long flags;
 	int len;
 
+	if (unlikely(target->transport_offline)) {
+		scmnd->result = DID_NO_CONNECT << 16;
+		scmnd->scsi_done(scmnd);
+		return 0;
+	}
+
 	spin_lock_irqsave(&target->lock, flags);
 	iu = __srp_get_tx_iu(target, SRP_IU_CMD);
 	if (!iu)
@@ -1695,6 +1703,9 @@ static int srp_send_tsk_mgmt(struct srp_
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
 
+	if (!target->connected || target->qp_in_error)
+		return -1;
+
 	init_completion(&target->tsk_mgmt_done);
 
 	spin_lock_irq(&target->lock);
@@ -1736,7 +1747,7 @@ static int srp_abort(struct scsi_cmnd *s
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
 
-	if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd))
+	if (!req || !srp_claim_req(target, req, scmnd))
 		return FAILED;
 	srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
 			  SRP_TSK_ABORT_TASK);
@@ -1754,8 +1765,6 @@ static int srp_reset_device(struct scsi_
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
 
-	if (target->qp_in_error)
-		return FAILED;
 	if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun,
 			      SRP_TSK_LUN_RESET))
 		return FAILED;
@@ -1972,7 +1981,6 @@ static int srp_add_target(struct srp_hos
 	spin_unlock(&host->target_lock);
 
 	target->state = SRP_TARGET_LIVE;
-	target->connected = false;
 
 	scsi_scan_target(&target->scsi_host->shost_gendev,
 			 0, target->scsi_id, SCAN_WILD_CARD, 0);
diff -druNp linux-libre-3.8-gnu1/drivers/infiniband/ulp/srp/ib_srp.h linux-libre-3.8.13-gnu1/drivers/infiniband/ulp/srp/ib_srp.h
--- linux-libre-3.8-gnu1/drivers/infiniband/ulp/srp/ib_srp.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/infiniband/ulp/srp/ib_srp.h	2013-05-11 16:57:46.000000000 -0400
@@ -140,6 +140,7 @@ struct srp_target_port {
 	unsigned int		cmd_sg_cnt;
 	unsigned int		indirect_size;
 	bool			allow_ext_sg;
+	bool			transport_offline;
 
 	/* Everything above this point is used in the hot path of
 	 * command processing. Try to keep them packed into cachelines.
diff -druNp linux-libre-3.8-gnu1/drivers/iommu/amd_iommu.c linux-libre-3.8.13-gnu1/drivers/iommu/amd_iommu.c
--- linux-libre-3.8-gnu1/drivers/iommu/amd_iommu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/iommu/amd_iommu.c	2013-05-11 16:57:46.000000000 -0400
@@ -2466,18 +2466,16 @@ static int device_change_notifier(struct
 
 		/* allocate a protection domain if a device is added */
 		dma_domain = find_protection_domain(devid);
-		if (dma_domain)
-			goto out;
-		dma_domain = dma_ops_domain_alloc();
-		if (!dma_domain)
-			goto out;
-		dma_domain->target_dev = devid;
-
-		spin_lock_irqsave(&iommu_pd_list_lock, flags);
-		list_add_tail(&dma_domain->list, &iommu_pd_list);
-		spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+		if (!dma_domain) {
+			dma_domain = dma_ops_domain_alloc();
+			if (!dma_domain)
+				goto out;
+			dma_domain->target_dev = devid;
 
-		dev_data = get_dev_data(dev);
+			spin_lock_irqsave(&iommu_pd_list_lock, flags);
+			list_add_tail(&dma_domain->list, &iommu_pd_list);
+			spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+		}
 
 		dev->archdata.dma_ops = &amd_iommu_dma_ops;
 
@@ -3950,6 +3948,9 @@ static struct irq_remap_table *get_irq_t
 	if (!table)
 		goto out;
 
+	/* Initialize table spin-lock */
+	spin_lock_init(&table->lock);
+
 	if (ioapic)
 		/* Keep the first 32 indexes free for IOAPIC interrupts */
 		table->min_index = 32;
diff -druNp linux-libre-3.8-gnu1/drivers/iommu/amd_iommu_init.c linux-libre-3.8.13-gnu1/drivers/iommu/amd_iommu_init.c
--- linux-libre-3.8-gnu1/drivers/iommu/amd_iommu_init.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/iommu/amd_iommu_init.c	2013-05-11 16:57:46.000000000 -0400
@@ -1876,11 +1876,6 @@ static int amd_iommu_init_dma(void)
 	struct amd_iommu *iommu;
 	int ret;
 
-	init_device_table_dma();
-
-	for_each_iommu(iommu)
-		iommu_flush_all_caches(iommu);
-
 	if (iommu_pass_through)
 		ret = amd_iommu_init_passthrough();
 	else
@@ -1889,6 +1884,11 @@ static int amd_iommu_init_dma(void)
 	if (ret)
 		return ret;
 
+	init_device_table_dma();
+
+	for_each_iommu(iommu)
+		iommu_flush_all_caches(iommu);
+
 	amd_iommu_init_api();
 
 	amd_iommu_init_notifier();
diff -druNp linux-libre-3.8-gnu1/drivers/iommu/intel-iommu.c linux-libre-3.8.13-gnu1/drivers/iommu/intel-iommu.c
--- linux-libre-3.8-gnu1/drivers/iommu/intel-iommu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/iommu/intel-iommu.c	2013-05-11 16:57:46.000000000 -0400
@@ -4253,13 +4253,19 @@ static void quirk_iommu_rwbf(struct pci_
 {
 	/*
 	 * Mobile 4 Series Chipset neglects to set RWBF capability,
-	 * but needs it:
+	 * but needs it. Same seems to hold for the desktop versions.
 	 */
 	printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
 	rwbf_quirk = 1;
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
 
 #define GGC 0x52
 #define GGC_MEMORY_SIZE_MASK	(0xf << 8)
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-bufio.c linux-libre-3.8.13-gnu1/drivers/md/dm-bufio.c
--- linux-libre-3.8-gnu1/drivers/md/dm-bufio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-bufio.c	2013-05-11 16:57:46.000000000 -0400
@@ -1026,6 +1026,8 @@ void dm_bufio_prefetch(struct dm_bufio_c
 {
 	struct blk_plug plug;
 
+	BUG_ON(dm_bufio_in_request());
+
 	blk_start_plug(&plug);
 	dm_bufio_lock(c);
 
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm.c linux-libre-3.8.13-gnu1/drivers/md/dm.c
--- linux-libre-3.8-gnu1/drivers/md/dm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm.c	2013-05-11 16:57:46.000000000 -0400
@@ -1973,15 +1973,27 @@ static void __bind_mempools(struct mappe
 {
 	struct dm_md_mempools *p = dm_table_get_md_mempools(t);
 
-	if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) {
-		/*
-		 * The md already has necessary mempools. Reload just the
-		 * bioset because front_pad may have changed because
-		 * a different table was loaded.
-		 */
-		bioset_free(md->bs);
-		md->bs = p->bs;
-		p->bs = NULL;
+	if (md->io_pool && md->bs) {
+		/* The md already has necessary mempools. */
+		if (dm_table_get_type(t) == DM_TYPE_BIO_BASED) {
+			/*
+			 * Reload bioset because front_pad may have changed
+			 * because a different table was loaded.
+			 */
+			bioset_free(md->bs);
+			md->bs = p->bs;
+			p->bs = NULL;
+		} else if (dm_table_get_type(t) == DM_TYPE_REQUEST_BASED) {
+			BUG_ON(!md->tio_pool);
+			/*
+			 * There's no need to reload with request-based dm
+			 * because the size of front_pad doesn't change.
+			 * Note for future: If you are to reload bioset,
+			 * prep-ed requests in the queue may refer
+			 * to bio from the old bioset, so you must walk
+			 * through the queue to unprep.
+			 */
+		}
 		goto out;
 	}
 
@@ -2421,7 +2433,7 @@ static void dm_queue_flush(struct mapped
  */
 struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
 {
-	struct dm_table *live_map, *map = ERR_PTR(-EINVAL);
+	struct dm_table *live_map = NULL, *map = ERR_PTR(-EINVAL);
 	struct queue_limits limits;
 	int r;
 
@@ -2444,10 +2456,12 @@ struct dm_table *dm_swap_table(struct ma
 		dm_table_put(live_map);
 	}
 
-	r = dm_calculate_queue_limits(table, &limits);
-	if (r) {
-		map = ERR_PTR(r);
-		goto out;
+	if (!live_map) {
+		r = dm_calculate_queue_limits(table, &limits);
+		if (r) {
+			map = ERR_PTR(r);
+			goto out;
+		}
 	}
 
 	map = __bind(md, table, &limits);
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-crypt.c linux-libre-3.8.13-gnu1/drivers/md/dm-crypt.c
--- linux-libre-3.8-gnu1/drivers/md/dm-crypt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-crypt.c	2013-05-11 16:57:46.000000000 -0400
@@ -1234,20 +1234,6 @@ static int crypt_decode_key(u8 *key, cha
 	return 0;
 }
 
-/*
- * Encode key into its hex representation
- */
-static void crypt_encode_key(char *hex, u8 *key, unsigned int size)
-{
-	unsigned int i;
-
-	for (i = 0; i < size; i++) {
-		sprintf(hex, "%02x", *key);
-		hex += 2;
-		key++;
-	}
-}
-
 static void crypt_free_tfms(struct crypt_config *cc)
 {
 	unsigned i;
@@ -1717,11 +1703,11 @@ static int crypt_map(struct dm_target *t
 	return DM_MAPIO_SUBMITTED;
 }
 
-static int crypt_status(struct dm_target *ti, status_type_t type,
-			unsigned status_flags, char *result, unsigned maxlen)
+static void crypt_status(struct dm_target *ti, status_type_t type,
+			 unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct crypt_config *cc = ti->private;
-	unsigned int sz = 0;
+	unsigned i, sz = 0;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -1731,17 +1717,11 @@ static int crypt_status(struct dm_target
 	case STATUSTYPE_TABLE:
 		DMEMIT("%s ", cc->cipher_string);
 
-		if (cc->key_size > 0) {
-			if ((maxlen - sz) < ((cc->key_size << 1) + 1))
-				return -ENOMEM;
-
-			crypt_encode_key(result + sz, cc->key, cc->key_size);
-			sz += cc->key_size << 1;
-		} else {
-			if (sz >= maxlen)
-				return -ENOMEM;
-			result[sz++] = '-';
-		}
+		if (cc->key_size > 0)
+			for (i = 0; i < cc->key_size; i++)
+				DMEMIT("%02x", cc->key[i]);
+		else
+			DMEMIT("-");
 
 		DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
 				cc->dev->name, (unsigned long long)cc->start);
@@ -1751,7 +1731,6 @@ static int crypt_status(struct dm_target
 
 		break;
 	}
-	return 0;
 }
 
 static void crypt_postsuspend(struct dm_target *ti)
@@ -1845,7 +1824,7 @@ static int crypt_iterate_devices(struct
 
 static struct target_type crypt_target = {
 	.name   = "crypt",
-	.version = {1, 12, 0},
+	.version = {1, 12, 1},
 	.module = THIS_MODULE,
 	.ctr    = crypt_ctr,
 	.dtr    = crypt_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-delay.c linux-libre-3.8.13-gnu1/drivers/md/dm-delay.c
--- linux-libre-3.8-gnu1/drivers/md/dm-delay.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-delay.c	2013-05-11 16:57:46.000000000 -0400
@@ -293,8 +293,8 @@ static int delay_map(struct dm_target *t
 	return delay_bio(dc, dc->read_delay, bio);
 }
 
-static int delay_status(struct dm_target *ti, status_type_t type,
-			unsigned status_flags, char *result, unsigned maxlen)
+static void delay_status(struct dm_target *ti, status_type_t type,
+			 unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct delay_c *dc = ti->private;
 	int sz = 0;
@@ -314,8 +314,6 @@ static int delay_status(struct dm_target
 			       dc->write_delay);
 		break;
 	}
-
-	return 0;
 }
 
 static int delay_iterate_devices(struct dm_target *ti,
@@ -337,7 +335,7 @@ out:
 
 static struct target_type delay_target = {
 	.name	     = "delay",
-	.version     = {1, 2, 0},
+	.version     = {1, 2, 1},
 	.module      = THIS_MODULE,
 	.ctr	     = delay_ctr,
 	.dtr	     = delay_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-flakey.c linux-libre-3.8.13-gnu1/drivers/md/dm-flakey.c
--- linux-libre-3.8-gnu1/drivers/md/dm-flakey.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-flakey.c	2013-05-11 16:57:46.000000000 -0400
@@ -337,8 +337,8 @@ static int flakey_end_io(struct dm_targe
 	return error;
 }
 
-static int flakey_status(struct dm_target *ti, status_type_t type,
-			 unsigned status_flags, char *result, unsigned maxlen)
+static void flakey_status(struct dm_target *ti, status_type_t type,
+			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	unsigned sz = 0;
 	struct flakey_c *fc = ti->private;
@@ -368,7 +368,6 @@ static int flakey_status(struct dm_targe
 
 		break;
 	}
-	return 0;
 }
 
 static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
@@ -411,7 +410,7 @@ static int flakey_iterate_devices(struct
 
 static struct target_type flakey_target = {
 	.name   = "flakey",
-	.version = {1, 3, 0},
+	.version = {1, 3, 1},
 	.module = THIS_MODULE,
 	.ctr    = flakey_ctr,
 	.dtr    = flakey_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-ioctl.c linux-libre-3.8.13-gnu1/drivers/md/dm-ioctl.c
--- linux-libre-3.8-gnu1/drivers/md/dm-ioctl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-ioctl.c	2013-05-11 16:57:46.000000000 -0400
@@ -1067,6 +1067,7 @@ static void retrieve_status(struct dm_ta
 	num_targets = dm_table_get_num_targets(table);
 	for (i = 0; i < num_targets; i++) {
 		struct dm_target *ti = dm_table_get_target(table, i);
+		size_t l;
 
 		remaining = len - (outptr - outbuf);
 		if (remaining <= sizeof(struct dm_target_spec)) {
@@ -1093,14 +1094,17 @@ static void retrieve_status(struct dm_ta
 		if (ti->type->status) {
 			if (param->flags & DM_NOFLUSH_FLAG)
 				status_flags |= DM_STATUS_NOFLUSH_FLAG;
-			if (ti->type->status(ti, type, status_flags, outptr, remaining)) {
-				param->flags |= DM_BUFFER_FULL_FLAG;
-				break;
-			}
+			ti->type->status(ti, type, status_flags, outptr, remaining);
 		} else
 			outptr[0] = '\0';
 
-		outptr += strlen(outptr) + 1;
+		l = strlen(outptr) + 1;
+		if (l == remaining) {
+			param->flags |= DM_BUFFER_FULL_FLAG;
+			break;
+		}
+
+		outptr += l;
 		used = param->data_start + (outptr - outbuf);
 
 		outptr = align_ptr(outptr);
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-linear.c linux-libre-3.8.13-gnu1/drivers/md/dm-linear.c
--- linux-libre-3.8-gnu1/drivers/md/dm-linear.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-linear.c	2013-05-11 16:57:46.000000000 -0400
@@ -95,8 +95,8 @@ static int linear_map(struct dm_target *
 	return DM_MAPIO_REMAPPED;
 }
 
-static int linear_status(struct dm_target *ti, status_type_t type,
-			 unsigned status_flags, char *result, unsigned maxlen)
+static void linear_status(struct dm_target *ti, status_type_t type,
+			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct linear_c *lc = (struct linear_c *) ti->private;
 
@@ -110,7 +110,6 @@ static int linear_status(struct dm_targe
 				(unsigned long long)lc->start);
 		break;
 	}
-	return 0;
 }
 
 static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
@@ -155,7 +154,7 @@ static int linear_iterate_devices(struct
 
 static struct target_type linear_target = {
 	.name   = "linear",
-	.version = {1, 2, 0},
+	.version = {1, 2, 1},
 	.module = THIS_MODULE,
 	.ctr    = linear_ctr,
 	.dtr    = linear_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-mpath.c linux-libre-3.8.13-gnu1/drivers/md/dm-mpath.c
--- linux-libre-3.8-gnu1/drivers/md/dm-mpath.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-mpath.c	2013-05-11 16:57:46.000000000 -0400
@@ -1378,8 +1378,8 @@ static void multipath_resume(struct dm_t
  *     [priority selector-name num_ps_args [ps_args]*
  *      num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
  */
-static int multipath_status(struct dm_target *ti, status_type_t type,
-			    unsigned status_flags, char *result, unsigned maxlen)
+static void multipath_status(struct dm_target *ti, status_type_t type,
+			     unsigned status_flags, char *result, unsigned maxlen)
 {
 	int sz = 0;
 	unsigned long flags;
@@ -1485,8 +1485,6 @@ static int multipath_status(struct dm_ta
 	}
 
 	spin_unlock_irqrestore(&m->lock, flags);
-
-	return 0;
 }
 
 static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
@@ -1695,7 +1693,7 @@ out:
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
 	.name = "multipath",
-	.version = {1, 5, 0},
+	.version = {1, 5, 1},
 	.module = THIS_MODULE,
 	.ctr = multipath_ctr,
 	.dtr = multipath_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-raid1.c linux-libre-3.8.13-gnu1/drivers/md/dm-raid1.c
--- linux-libre-3.8-gnu1/drivers/md/dm-raid1.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-raid1.c	2013-05-11 16:57:46.000000000 -0400
@@ -1347,8 +1347,8 @@ static char device_status_char(struct mi
 }
 
 
-static int mirror_status(struct dm_target *ti, status_type_t type,
-			 unsigned status_flags, char *result, unsigned maxlen)
+static void mirror_status(struct dm_target *ti, status_type_t type,
+			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	unsigned int m, sz = 0;
 	struct mirror_set *ms = (struct mirror_set *) ti->private;
@@ -1383,8 +1383,6 @@ static int mirror_status(struct dm_targe
 		if (ms->features & DM_RAID1_HANDLE_ERRORS)
 			DMEMIT(" 1 handle_errors");
 	}
-
-	return 0;
 }
 
 static int mirror_iterate_devices(struct dm_target *ti,
@@ -1403,7 +1401,7 @@ static int mirror_iterate_devices(struct
 
 static struct target_type mirror_target = {
 	.name	 = "mirror",
-	.version = {1, 13, 1},
+	.version = {1, 13, 2},
 	.module	 = THIS_MODULE,
 	.ctr	 = mirror_ctr,
 	.dtr	 = mirror_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-raid.c linux-libre-3.8.13-gnu1/drivers/md/dm-raid.c
--- linux-libre-3.8-gnu1/drivers/md/dm-raid.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-raid.c	2013-05-11 16:57:46.000000000 -0400
@@ -1201,8 +1201,8 @@ static int raid_map(struct dm_target *ti
 	return DM_MAPIO_SUBMITTED;
 }
 
-static int raid_status(struct dm_target *ti, status_type_t type,
-		       unsigned status_flags, char *result, unsigned maxlen)
+static void raid_status(struct dm_target *ti, status_type_t type,
+			unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct raid_set *rs = ti->private;
 	unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
@@ -1344,8 +1344,6 @@ static int raid_status(struct dm_target
 				DMEMIT(" -");
 		}
 	}
-
-	return 0;
 }
 
 static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
@@ -1405,7 +1403,7 @@ static void raid_resume(struct dm_target
 
 static struct target_type raid_target = {
 	.name = "raid",
-	.version = {1, 4, 1},
+	.version = {1, 4, 2},
 	.module = THIS_MODULE,
 	.ctr = raid_ctr,
 	.dtr = raid_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-snap.c linux-libre-3.8.13-gnu1/drivers/md/dm-snap.c
--- linux-libre-3.8-gnu1/drivers/md/dm-snap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-snap.c	2013-05-11 16:57:46.000000000 -0400
@@ -1837,8 +1837,8 @@ static void snapshot_merge_resume(struct
 	start_merge(s);
 }
 
-static int snapshot_status(struct dm_target *ti, status_type_t type,
-			   unsigned status_flags, char *result, unsigned maxlen)
+static void snapshot_status(struct dm_target *ti, status_type_t type,
+			    unsigned status_flags, char *result, unsigned maxlen)
 {
 	unsigned sz = 0;
 	struct dm_snapshot *snap = ti->private;
@@ -1884,8 +1884,6 @@ static int snapshot_status(struct dm_tar
 					  maxlen - sz);
 		break;
 	}
-
-	return 0;
 }
 
 static int snapshot_iterate_devices(struct dm_target *ti,
@@ -2139,8 +2137,8 @@ static void origin_resume(struct dm_targ
 	ti->max_io_len = get_origin_minimum_chunksize(dev->bdev);
 }
 
-static int origin_status(struct dm_target *ti, status_type_t type,
-			 unsigned status_flags, char *result, unsigned maxlen)
+static void origin_status(struct dm_target *ti, status_type_t type,
+			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct dm_dev *dev = ti->private;
 
@@ -2153,8 +2151,6 @@ static int origin_status(struct dm_targe
 		snprintf(result, maxlen, "%s", dev->name);
 		break;
 	}
-
-	return 0;
 }
 
 static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
@@ -2181,7 +2177,7 @@ static int origin_iterate_devices(struct
 
 static struct target_type origin_target = {
 	.name    = "snapshot-origin",
-	.version = {1, 8, 0},
+	.version = {1, 8, 1},
 	.module  = THIS_MODULE,
 	.ctr     = origin_ctr,
 	.dtr     = origin_dtr,
@@ -2194,7 +2190,7 @@ static struct target_type origin_target
 
 static struct target_type snapshot_target = {
 	.name    = "snapshot",
-	.version = {1, 11, 0},
+	.version = {1, 11, 1},
 	.module  = THIS_MODULE,
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
@@ -2307,3 +2303,5 @@ module_exit(dm_snapshot_exit);
 MODULE_DESCRIPTION(DM_NAME " snapshot target");
 MODULE_AUTHOR("Joe Thornber");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("dm-snapshot-origin");
+MODULE_ALIAS("dm-snapshot-merge");
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-stripe.c linux-libre-3.8.13-gnu1/drivers/md/dm-stripe.c
--- linux-libre-3.8-gnu1/drivers/md/dm-stripe.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-stripe.c	2013-05-11 16:57:46.000000000 -0400
@@ -312,8 +312,8 @@ static int stripe_map(struct dm_target *
  *
  */
 
-static int stripe_status(struct dm_target *ti, status_type_t type,
-			 unsigned status_flags, char *result, unsigned maxlen)
+static void stripe_status(struct dm_target *ti, status_type_t type,
+			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct stripe_c *sc = (struct stripe_c *) ti->private;
 	char buffer[sc->stripes + 1];
@@ -340,7 +340,6 @@ static int stripe_status(struct dm_targe
 			    (unsigned long long)sc->stripe[i].physical_start);
 		break;
 	}
-	return 0;
 }
 
 static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
@@ -428,7 +427,7 @@ static int stripe_merge(struct dm_target
 
 static struct target_type stripe_target = {
 	.name   = "striped",
-	.version = {1, 5, 0},
+	.version = {1, 5, 1},
 	.module = THIS_MODULE,
 	.ctr    = stripe_ctr,
 	.dtr    = stripe_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-thin.c linux-libre-3.8.13-gnu1/drivers/md/dm-thin.c
--- linux-libre-3.8-gnu1/drivers/md/dm-thin.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-thin.c	2013-05-11 16:57:46.000000000 -0400
@@ -2299,8 +2299,8 @@ static void emit_flags(struct pool_featu
  *    <transaction id> <used metadata sectors>/<total metadata sectors>
  *    <used data sectors>/<total data sectors> <held metadata root>
  */
-static int pool_status(struct dm_target *ti, status_type_t type,
-		       unsigned status_flags, char *result, unsigned maxlen)
+static void pool_status(struct dm_target *ti, status_type_t type,
+			unsigned status_flags, char *result, unsigned maxlen)
 {
 	int r;
 	unsigned sz = 0;
@@ -2326,32 +2326,41 @@ static int pool_status(struct dm_target
 		if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
 			(void) commit_or_fallback(pool);
 
-		r = dm_pool_get_metadata_transaction_id(pool->pmd,
-							&transaction_id);
-		if (r)
-			return r;
+		r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id);
+		if (r) {
+			DMERR("dm_pool_get_metadata_transaction_id returned %d", r);
+			goto err;
+		}
 
-		r = dm_pool_get_free_metadata_block_count(pool->pmd,
-							  &nr_free_blocks_metadata);
-		if (r)
-			return r;
+		r = dm_pool_get_free_metadata_block_count(pool->pmd, &nr_free_blocks_metadata);
+		if (r) {
+			DMERR("dm_pool_get_free_metadata_block_count returned %d", r);
+			goto err;
+		}
 
 		r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata);
-		if (r)
-			return r;
+		if (r) {
+			DMERR("dm_pool_get_metadata_dev_size returned %d", r);
+			goto err;
+		}
 
-		r = dm_pool_get_free_block_count(pool->pmd,
-						 &nr_free_blocks_data);
-		if (r)
-			return r;
+		r = dm_pool_get_free_block_count(pool->pmd, &nr_free_blocks_data);
+		if (r) {
+			DMERR("dm_pool_get_free_block_count returned %d", r);
+			goto err;
+		}
 
 		r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data);
-		if (r)
-			return r;
+		if (r) {
+			DMERR("dm_pool_get_data_dev_size returned %d", r);
+			goto err;
+		}
 
 		r = dm_pool_get_metadata_snap(pool->pmd, &held_root);
-		if (r)
-			return r;
+		if (r) {
+			DMERR("dm_pool_get_metadata_snap returned %d", r);
+			goto err;
+		}
 
 		DMEMIT("%llu %llu/%llu %llu/%llu ",
 		       (unsigned long long)transaction_id,
@@ -2388,8 +2397,10 @@ static int pool_status(struct dm_target
 		emit_flags(&pt->requested_pf, result, sz, maxlen);
 		break;
 	}
+	return;
 
-	return 0;
+err:
+	DMEMIT("Error");
 }
 
 static int pool_iterate_devices(struct dm_target *ti,
@@ -2468,7 +2479,7 @@ static struct target_type pool_target =
 	.name = "thin-pool",
 	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
 		    DM_TARGET_IMMUTABLE,
-	.version = {1, 6, 0},
+	.version = {1, 7, 0},
 	.module = THIS_MODULE,
 	.ctr = pool_ctr,
 	.dtr = pool_dtr,
@@ -2676,8 +2687,8 @@ static void thin_postsuspend(struct dm_t
 /*
  * <nr mapped sectors> <highest mapped sector>
  */
-static int thin_status(struct dm_target *ti, status_type_t type,
-		       unsigned status_flags, char *result, unsigned maxlen)
+static void thin_status(struct dm_target *ti, status_type_t type,
+			unsigned status_flags, char *result, unsigned maxlen)
 {
 	int r;
 	ssize_t sz = 0;
@@ -2687,7 +2698,7 @@ static int thin_status(struct dm_target
 
 	if (get_pool_mode(tc->pool) == PM_FAIL) {
 		DMEMIT("Fail");
-		return 0;
+		return;
 	}
 
 	if (!tc->td)
@@ -2696,12 +2707,16 @@ static int thin_status(struct dm_target
 		switch (type) {
 		case STATUSTYPE_INFO:
 			r = dm_thin_get_mapped_count(tc->td, &mapped);
-			if (r)
-				return r;
+			if (r) {
+				DMERR("dm_thin_get_mapped_count returned %d", r);
+				goto err;
+			}
 
 			r = dm_thin_get_highest_mapped_block(tc->td, &highest);
-			if (r < 0)
-				return r;
+			if (r < 0) {
+				DMERR("dm_thin_get_highest_mapped_block returned %d", r);
+				goto err;
+			}
 
 			DMEMIT("%llu ", mapped * tc->pool->sectors_per_block);
 			if (r)
@@ -2721,7 +2736,10 @@ static int thin_status(struct dm_target
 		}
 	}
 
-	return 0;
+	return;
+
+err:
+	DMEMIT("Error");
 }
 
 static int thin_iterate_devices(struct dm_target *ti,
@@ -2748,7 +2766,7 @@ static int thin_iterate_devices(struct d
 
 static struct target_type thin_target = {
 	.name = "thin",
-	.version = {1, 7, 0},
+	.version = {1, 8, 0},
 	.module	= THIS_MODULE,
 	.ctr = thin_ctr,
 	.dtr = thin_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/dm-verity.c linux-libre-3.8.13-gnu1/drivers/md/dm-verity.c
--- linux-libre-3.8-gnu1/drivers/md/dm-verity.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/dm-verity.c	2013-05-11 16:57:46.000000000 -0400
@@ -93,6 +93,13 @@ struct dm_verity_io {
 	 */
 };
 
+struct dm_verity_prefetch_work {
+	struct work_struct work;
+	struct dm_verity *v;
+	sector_t block;
+	unsigned n_blocks;
+};
+
 static struct shash_desc *io_hash_desc(struct dm_verity *v, struct dm_verity_io *io)
 {
 	return (struct shash_desc *)(io + 1);
@@ -424,15 +431,18 @@ static void verity_end_io(struct bio *bi
  * The root buffer is not prefetched, it is assumed that it will be cached
  * all the time.
  */
-static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io)
+static void verity_prefetch_io(struct work_struct *work)
 {
+	struct dm_verity_prefetch_work *pw =
+		container_of(work, struct dm_verity_prefetch_work, work);
+	struct dm_verity *v = pw->v;
 	int i;
 
 	for (i = v->levels - 2; i >= 0; i--) {
 		sector_t hash_block_start;
 		sector_t hash_block_end;
-		verity_hash_at_level(v, io->block, i, &hash_block_start, NULL);
-		verity_hash_at_level(v, io->block + io->n_blocks - 1, i, &hash_block_end, NULL);
+		verity_hash_at_level(v, pw->block, i, &hash_block_start, NULL);
+		verity_hash_at_level(v, pw->block + pw->n_blocks - 1, i, &hash_block_end, NULL);
 		if (!i) {
 			unsigned cluster = ACCESS_ONCE(dm_verity_prefetch_cluster);
 
@@ -452,6 +462,25 @@ no_prefetch_cluster:
 		dm_bufio_prefetch(v->bufio, hash_block_start,
 				  hash_block_end - hash_block_start + 1);
 	}
+
+	kfree(pw);
+}
+
+static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
+{
+	struct dm_verity_prefetch_work *pw;
+
+	pw = kmalloc(sizeof(struct dm_verity_prefetch_work),
+		GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+
+	if (!pw)
+		return;
+
+	INIT_WORK(&pw->work, verity_prefetch_io);
+	pw->v = v;
+	pw->block = io->block;
+	pw->n_blocks = io->n_blocks;
+	queue_work(v->verify_wq, &pw->work);
 }
 
 /*
@@ -498,7 +527,7 @@ static int verity_map(struct dm_target *
 	memcpy(io->io_vec, bio_iovec(bio),
 	       io->io_vec_size * sizeof(struct bio_vec));
 
-	verity_prefetch_io(v, io);
+	verity_submit_prefetch(v, io);
 
 	generic_make_request(bio);
 
@@ -508,8 +537,8 @@ static int verity_map(struct dm_target *
 /*
  * Status: V (valid) or C (corruption found)
  */
-static int verity_status(struct dm_target *ti, status_type_t type,
-			 unsigned status_flags, char *result, unsigned maxlen)
+static void verity_status(struct dm_target *ti, status_type_t type,
+			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct dm_verity *v = ti->private;
 	unsigned sz = 0;
@@ -540,8 +569,6 @@ static int verity_status(struct dm_targe
 				DMEMIT("%02x", v->salt[x]);
 		break;
 	}
-
-	return 0;
 }
 
 static int verity_ioctl(struct dm_target *ti, unsigned cmd,
@@ -860,7 +887,7 @@ bad:
 
 static struct target_type verity_target = {
 	.name		= "verity",
-	.version	= {1, 1, 0},
+	.version	= {1, 2, 0},
 	.module		= THIS_MODULE,
 	.ctr		= verity_ctr,
 	.dtr		= verity_dtr,
diff -druNp linux-libre-3.8-gnu1/drivers/md/md.c linux-libre-3.8.13-gnu1/drivers/md/md.c
--- linux-libre-3.8-gnu1/drivers/md/md.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/md.c	2013-05-11 16:57:46.000000000 -0400
@@ -307,6 +307,10 @@ static void md_make_request(struct reque
 		bio_io_error(bio);
 		return;
 	}
+	if (mddev->ro == 1 && unlikely(rw == WRITE)) {
+		bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS);
+		return;
+	}
 	smp_rmb(); /* Ensure implications of  'active' are visible */
 	rcu_read_lock();
 	if (mddev->suspended) {
@@ -1560,8 +1564,8 @@ static int super_1_load(struct md_rdev *
 					     sector, count, 1) == 0)
 				return -EINVAL;
 		}
-	} else if (sb->bblog_offset == 0)
-		rdev->badblocks.shift = -1;
+	} else if (sb->bblog_offset != 0)
+		rdev->badblocks.shift = 0;
 
 	if (!refdev) {
 		ret = 1;
@@ -2994,6 +2998,9 @@ rdev_size_store(struct md_rdev *rdev, co
 		} else if (!sectors)
 			sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) -
 				rdev->data_offset;
+		if (!my_mddev->pers->resize)
+			/* Cannot change size for RAID0 or Linear etc */
+			return -EINVAL;
 	}
 	if (sectors < my_mddev->dev_sectors)
 		return -EINVAL; /* component must fit device */
@@ -3214,7 +3221,7 @@ int md_rdev_init(struct md_rdev *rdev)
 	 * be used - I wonder if that matters
 	 */
 	rdev->badblocks.count = 0;
-	rdev->badblocks.shift = 0;
+	rdev->badblocks.shift = -1; /* disabled until explicitly enabled */
 	rdev->badblocks.page = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	seqlock_init(&rdev->badblocks.lock);
 	if (rdev->badblocks.page == NULL)
@@ -3286,9 +3293,6 @@ static struct md_rdev *md_import_device(
 			goto abort_free;
 		}
 	}
-	if (super_format == -1)
-		/* hot-add for 0.90, or non-persistent: so no badblocks */
-		rdev->badblocks.shift = -1;
 
 	return rdev;
 
diff -druNp linux-libre-3.8-gnu1/drivers/md/persistent-data/dm-btree-remove.c linux-libre-3.8.13-gnu1/drivers/md/persistent-data/dm-btree-remove.c
--- linux-libre-3.8-gnu1/drivers/md/persistent-data/dm-btree-remove.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/persistent-data/dm-btree-remove.c	2013-05-11 16:57:46.000000000 -0400
@@ -139,15 +139,8 @@ struct child {
 	struct btree_node *n;
 };
 
-static struct dm_btree_value_type le64_type = {
-	.context = NULL,
-	.size = sizeof(__le64),
-	.inc = NULL,
-	.dec = NULL,
-	.equal = NULL
-};
-
-static int init_child(struct dm_btree_info *info, struct btree_node *parent,
+static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt,
+		      struct btree_node *parent,
 		      unsigned index, struct child *result)
 {
 	int r, inc;
@@ -164,7 +157,7 @@ static int init_child(struct dm_btree_in
 	result->n = dm_block_data(result->block);
 
 	if (inc)
-		inc_children(info->tm, result->n, &le64_type);
+		inc_children(info->tm, result->n, vt);
 
 	*((__le64 *) value_ptr(parent, index)) =
 		cpu_to_le64(dm_block_location(result->block));
@@ -236,7 +229,7 @@ static void __rebalance2(struct dm_btree
 }
 
 static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
-		      unsigned left_index)
+		      struct dm_btree_value_type *vt, unsigned left_index)
 {
 	int r;
 	struct btree_node *parent;
@@ -244,11 +237,11 @@ static int rebalance2(struct shadow_spin
 
 	parent = dm_block_data(shadow_current(s));
 
-	r = init_child(info, parent, left_index, &left);
+	r = init_child(info, vt, parent, left_index, &left);
 	if (r)
 		return r;
 
-	r = init_child(info, parent, left_index + 1, &right);
+	r = init_child(info, vt, parent, left_index + 1, &right);
 	if (r) {
 		exit_child(info, &left);
 		return r;
@@ -368,7 +361,7 @@ static void __rebalance3(struct dm_btree
 }
 
 static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
-		      unsigned left_index)
+		      struct dm_btree_value_type *vt, unsigned left_index)
 {
 	int r;
 	struct btree_node *parent = dm_block_data(shadow_current(s));
@@ -377,17 +370,17 @@ static int rebalance3(struct shadow_spin
 	/*
 	 * FIXME: fill out an array?
 	 */
-	r = init_child(info, parent, left_index, &left);
+	r = init_child(info, vt, parent, left_index, &left);
 	if (r)
 		return r;
 
-	r = init_child(info, parent, left_index + 1, &center);
+	r = init_child(info, vt, parent, left_index + 1, &center);
 	if (r) {
 		exit_child(info, &left);
 		return r;
 	}
 
-	r = init_child(info, parent, left_index + 2, &right);
+	r = init_child(info, vt, parent, left_index + 2, &right);
 	if (r) {
 		exit_child(info, &left);
 		exit_child(info, &center);
@@ -434,7 +427,8 @@ static int get_nr_entries(struct dm_tran
 }
 
 static int rebalance_children(struct shadow_spine *s,
-			      struct dm_btree_info *info, uint64_t key)
+			      struct dm_btree_info *info,
+			      struct dm_btree_value_type *vt, uint64_t key)
 {
 	int i, r, has_left_sibling, has_right_sibling;
 	uint32_t child_entries;
@@ -472,13 +466,13 @@ static int rebalance_children(struct sha
 	has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
 
 	if (!has_left_sibling)
-		r = rebalance2(s, info, i);
+		r = rebalance2(s, info, vt, i);
 
 	else if (!has_right_sibling)
-		r = rebalance2(s, info, i - 1);
+		r = rebalance2(s, info, vt, i - 1);
 
 	else
-		r = rebalance3(s, info, i - 1);
+		r = rebalance3(s, info, vt, i - 1);
 
 	return r;
 }
@@ -529,7 +523,7 @@ static int remove_raw(struct shadow_spin
 		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
 			return do_leaf(n, key, index);
 
-		r = rebalance_children(s, info, key);
+		r = rebalance_children(s, info, vt, key);
 		if (r)
 			break;
 
@@ -550,6 +544,14 @@ static int remove_raw(struct shadow_spin
 	return r;
 }
 
+static struct dm_btree_value_type le64_type = {
+	.context = NULL,
+	.size = sizeof(__le64),
+	.inc = NULL,
+	.dec = NULL,
+	.equal = NULL
+};
+
 int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
 		    uint64_t *keys, dm_block_t *new_root)
 {
diff -druNp linux-libre-3.8-gnu1/drivers/md/raid0.c linux-libre-3.8.13-gnu1/drivers/md/raid0.c
--- linux-libre-3.8-gnu1/drivers/md/raid0.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/raid0.c	2013-05-11 16:57:46.000000000 -0400
@@ -289,7 +289,7 @@ abort:
 	kfree(conf->strip_zone);
 	kfree(conf->devlist);
 	kfree(conf);
-	*private_conf = NULL;
+	*private_conf = ERR_PTR(err);
 	return err;
 }
 
@@ -411,7 +411,8 @@ static sector_t raid0_size(struct mddev
 		  "%s does not support generic reshape\n", __func__);
 
 	rdev_for_each(rdev, mddev)
-		array_sectors += rdev->sectors;
+		array_sectors += (rdev->sectors &
+				  ~(sector_t)(mddev->chunk_sectors-1));
 
 	return array_sectors;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/md/raid10.c linux-libre-3.8.13-gnu1/drivers/md/raid10.c
--- linux-libre-3.8-gnu1/drivers/md/raid10.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/raid10.c	2013-05-11 16:57:46.000000000 -0400
@@ -1073,6 +1073,7 @@ static void raid10_unplug(struct blk_plu
 		bio_list_merge(&conf->pending_bio_list, &plug->pending);
 		conf->pending_count += plug->pending_cnt;
 		spin_unlock_irq(&conf->device_lock);
+		wake_up(&conf->wait_barrier);
 		md_wakeup_thread(mddev->thread);
 		kfree(plug);
 		return;
@@ -1086,7 +1087,12 @@ static void raid10_unplug(struct blk_plu
 	while (bio) { /* submit pending writes */
 		struct bio *next = bio->bi_next;
 		bio->bi_next = NULL;
-		generic_make_request(bio);
+		if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+		    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+			/* Just ignore it */
+			bio_endio(bio, 0);
+		else
+			generic_make_request(bio);
 		bio = next;
 	}
 	kfree(plug);
@@ -1105,6 +1111,7 @@ static void make_request(struct mddev *m
 	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
 	const unsigned long do_discard = (bio->bi_rw
 					  & (REQ_DISCARD | REQ_SECURE));
+	const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME);
 	unsigned long flags;
 	struct md_rdev *blocked_rdev;
 	struct blk_plug_cb *cb;
@@ -1460,7 +1467,8 @@ retry_write:
 							      rdev));
 			mbio->bi_bdev = rdev->bdev;
 			mbio->bi_end_io	= raid10_end_write_request;
-			mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+			mbio->bi_rw =
+				WRITE | do_sync | do_fua | do_discard | do_same;
 			mbio->bi_private = r10_bio;
 
 			atomic_inc(&r10_bio->remaining);
@@ -1502,7 +1510,8 @@ retry_write:
 						   r10_bio, rdev));
 			mbio->bi_bdev = rdev->bdev;
 			mbio->bi_end_io	= raid10_end_write_request;
-			mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+			mbio->bi_rw =
+				WRITE | do_sync | do_fua | do_discard | do_same;
 			mbio->bi_private = r10_bio;
 
 			atomic_inc(&r10_bio->remaining);
@@ -3569,6 +3578,8 @@ static int run(struct mddev *mddev)
 	if (mddev->queue) {
 		blk_queue_max_discard_sectors(mddev->queue,
 					      mddev->chunk_sectors);
+		blk_queue_max_write_same_sectors(mddev->queue,
+						 mddev->chunk_sectors);
 		blk_queue_io_min(mddev->queue, chunk_size);
 		if (conf->geo.raid_disks % conf->geo.near_copies)
 			blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks);
diff -druNp linux-libre-3.8-gnu1/drivers/md/raid1.c linux-libre-3.8.13-gnu1/drivers/md/raid1.c
--- linux-libre-3.8-gnu1/drivers/md/raid1.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/raid1.c	2013-05-11 16:57:46.000000000 -0400
@@ -967,6 +967,7 @@ static void raid1_unplug(struct blk_plug
 		bio_list_merge(&conf->pending_bio_list, &plug->pending);
 		conf->pending_count += plug->pending_cnt;
 		spin_unlock_irq(&conf->device_lock);
+		wake_up(&conf->wait_barrier);
 		md_wakeup_thread(mddev->thread);
 		kfree(plug);
 		return;
@@ -980,7 +981,12 @@ static void raid1_unplug(struct blk_plug
 	while (bio) { /* submit pending writes */
 		struct bio *next = bio->bi_next;
 		bio->bi_next = NULL;
-		generic_make_request(bio);
+		if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+		    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+			/* Just ignore it */
+			bio_endio(bio, 0);
+		else
+			generic_make_request(bio);
 		bio = next;
 	}
 	kfree(plug);
@@ -1000,6 +1006,7 @@ static void make_request(struct mddev *m
 	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
 	const unsigned long do_discard = (bio->bi_rw
 					  & (REQ_DISCARD | REQ_SECURE));
+	const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME);
 	struct md_rdev *blocked_rdev;
 	struct blk_plug_cb *cb;
 	struct raid1_plug_cb *plug = NULL;
@@ -1301,7 +1308,8 @@ read_again:
 				   conf->mirrors[i].rdev->data_offset);
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= raid1_end_write_request;
-		mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard;
+		mbio->bi_rw =
+			WRITE | do_flush_fua | do_sync | do_discard | do_same;
 		mbio->bi_private = r1_bio;
 
 		atomic_inc(&r1_bio->remaining);
@@ -2818,6 +2826,9 @@ static int run(struct mddev *mddev)
 	if (IS_ERR(conf))
 		return PTR_ERR(conf);
 
+	if (mddev->queue)
+		blk_queue_max_write_same_sectors(mddev->queue,
+						 mddev->chunk_sectors);
 	rdev_for_each(rdev, mddev) {
 		if (!mddev->gendisk)
 			continue;
diff -druNp linux-libre-3.8-gnu1/drivers/md/raid5.c linux-libre-3.8.13-gnu1/drivers/md/raid5.c
--- linux-libre-3.8-gnu1/drivers/md/raid5.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/raid5.c	2013-05-11 16:57:46.000000000 -0400
@@ -674,9 +674,11 @@ static void ops_run_io(struct stripe_hea
 			bi->bi_next = NULL;
 			if (rrdev)
 				set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
-			trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
-					      bi, disk_devt(conf->mddev->gendisk),
-					      sh->dev[i].sector);
+
+			if (conf->mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
+						      bi, disk_devt(conf->mddev->gendisk),
+						      sh->dev[i].sector);
 			generic_make_request(bi);
 		}
 		if (rrdev) {
@@ -704,9 +706,10 @@ static void ops_run_io(struct stripe_hea
 			rbi->bi_io_vec[0].bv_offset = 0;
 			rbi->bi_size = STRIPE_SIZE;
 			rbi->bi_next = NULL;
-			trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
-					      rbi, disk_devt(conf->mddev->gendisk),
-					      sh->dev[i].sector);
+			if (conf->mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
+						      rbi, disk_devt(conf->mddev->gendisk),
+						      sh->dev[i].sector);
 			generic_make_request(rbi);
 		}
 		if (!rdev && !rrdev) {
@@ -2319,17 +2322,6 @@ schedule_reconstruction(struct stripe_he
 	int level = conf->level;
 
 	if (rcw) {
-		/* if we are not expanding this is a proper write request, and
-		 * there will be bios with new data to be drained into the
-		 * stripe cache
-		 */
-		if (!expand) {
-			sh->reconstruct_state = reconstruct_state_drain_run;
-			set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
-		} else
-			sh->reconstruct_state = reconstruct_state_run;
-
-		set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
 
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
@@ -2342,6 +2334,21 @@ schedule_reconstruction(struct stripe_he
 				s->locked++;
 			}
 		}
+		/* if we are not expanding this is a proper write request, and
+		 * there will be bios with new data to be drained into the
+		 * stripe cache
+		 */
+		if (!expand) {
+			if (!s->locked)
+				/* False alarm, nothing to do */
+				return;
+			sh->reconstruct_state = reconstruct_state_drain_run;
+			set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+		} else
+			sh->reconstruct_state = reconstruct_state_run;
+
+		set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
+
 		if (s->locked + conf->max_degraded == disks)
 			if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
 				atomic_inc(&conf->pending_full_writes);
@@ -2350,11 +2357,6 @@ schedule_reconstruction(struct stripe_he
 		BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
 			test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
 
-		sh->reconstruct_state = reconstruct_state_prexor_drain_run;
-		set_bit(STRIPE_OP_PREXOR, &s->ops_request);
-		set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
-		set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
-
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if (i == pd_idx)
@@ -2369,6 +2371,13 @@ schedule_reconstruction(struct stripe_he
 				s->locked++;
 			}
 		}
+		if (!s->locked)
+			/* False alarm - nothing to do */
+			return;
+		sh->reconstruct_state = reconstruct_state_prexor_drain_run;
+		set_bit(STRIPE_OP_PREXOR, &s->ops_request);
+		set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+		set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
 	}
 
 	/* keep the parity disk(s) locked while asynchronous operations
@@ -2603,6 +2612,8 @@ handle_failed_sync(struct r5conf *conf,
 	int i;
 
 	clear_bit(STRIPE_SYNCING, &sh->state);
+	if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags))
+		wake_up(&conf->wait_for_overlap);
 	s->syncing = 0;
 	s->replacing = 0;
 	/* There is nothing more to do for sync/check/repair.
@@ -2776,6 +2787,7 @@ static void handle_stripe_clean_event(st
 {
 	int i;
 	struct r5dev *dev;
+	int discard_pending = 0;
 
 	for (i = disks; i--; )
 		if (sh->dev[i].written) {
@@ -2804,9 +2816,23 @@ static void handle_stripe_clean_event(st
 						STRIPE_SECTORS,
 					 !test_bit(STRIPE_DEGRADED, &sh->state),
 						0);
-			}
-		} else if (test_bit(R5_Discard, &sh->dev[i].flags))
-			clear_bit(R5_Discard, &sh->dev[i].flags);
+			} else if (test_bit(R5_Discard, &dev->flags))
+				discard_pending = 1;
+		}
+	if (!discard_pending &&
+	    test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
+		clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
+		clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
+		if (sh->qd_idx >= 0) {
+			clear_bit(R5_Discard, &sh->dev[sh->qd_idx].flags);
+			clear_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags);
+		}
+		/* now that discard is done we can proceed with any sync */
+		clear_bit(STRIPE_DISCARD, &sh->state);
+		if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
+			set_bit(STRIPE_HANDLE, &sh->state);
+
+	}
 
 	if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
 		if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -2865,8 +2891,10 @@ static void handle_stripe_dirtying(struc
 	set_bit(STRIPE_HANDLE, &sh->state);
 	if (rmw < rcw && rmw > 0) {
 		/* prefer read-modify-write, but need to get some data */
-		blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d",
-				  (unsigned long long)sh->sector, rmw);
+		if (conf->mddev->queue)
+			blk_add_trace_msg(conf->mddev->queue,
+					  "raid5 rmw %llu %d",
+					  (unsigned long long)sh->sector, rmw);
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if ((dev->towrite || i == sh->pd_idx) &&
@@ -2916,7 +2944,7 @@ static void handle_stripe_dirtying(struc
 				}
 			}
 		}
-		if (rcw)
+		if (rcw && conf->mddev->queue)
 			blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d",
 					  (unsigned long long)sh->sector,
 					  rcw, qread, test_bit(STRIPE_DELAYED, &sh->state));
@@ -3456,9 +3484,15 @@ static void handle_stripe(struct stripe_
 		return;
 	}
 
-	if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
-		set_bit(STRIPE_SYNCING, &sh->state);
-		clear_bit(STRIPE_INSYNC, &sh->state);
+	if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+		spin_lock(&sh->stripe_lock);
+		/* Cannot process 'sync' concurrently with 'discard' */
+		if (!test_bit(STRIPE_DISCARD, &sh->state) &&
+		    test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+			set_bit(STRIPE_SYNCING, &sh->state);
+			clear_bit(STRIPE_INSYNC, &sh->state);
+		}
+		spin_unlock(&sh->stripe_lock);
 	}
 	clear_bit(STRIPE_DELAYED, &sh->state);
 
@@ -3618,6 +3652,8 @@ static void handle_stripe(struct stripe_
 	    test_bit(STRIPE_INSYNC, &sh->state)) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
 		clear_bit(STRIPE_SYNCING, &sh->state);
+		if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags))
+			wake_up(&conf->wait_for_overlap);
 	}
 
 	/* If the failed drives are just a ReadError, then we might need
@@ -4023,9 +4059,10 @@ static int chunk_aligned_read(struct mdd
 		atomic_inc(&conf->active_aligned_reads);
 		spin_unlock_irq(&conf->device_lock);
 
-		trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
-				      align_bi, disk_devt(mddev->gendisk),
-				      raid_bio->bi_sector);
+		if (mddev->gendisk)
+			trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
+					      align_bi, disk_devt(mddev->gendisk),
+					      raid_bio->bi_sector);
 		generic_make_request(align_bi);
 		return 1;
 	} else {
@@ -4119,7 +4156,8 @@ static void raid5_unplug(struct blk_plug
 		}
 		spin_unlock_irq(&conf->device_lock);
 	}
-	trace_block_unplug(mddev->queue, cnt, !from_schedule);
+	if (mddev->queue)
+		trace_block_unplug(mddev->queue, cnt, !from_schedule);
 	kfree(cb);
 }
 
@@ -4182,6 +4220,13 @@ static void make_discard_request(struct
 		sh = get_active_stripe(conf, logical_sector, 0, 0, 0);
 		prepare_to_wait(&conf->wait_for_overlap, &w,
 				TASK_UNINTERRUPTIBLE);
+		set_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags);
+		if (test_bit(STRIPE_SYNCING, &sh->state)) {
+			release_stripe(sh);
+			schedule();
+			goto again;
+		}
+		clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags);
 		spin_lock_irq(&sh->stripe_lock);
 		for (d = 0; d < conf->raid_disks; d++) {
 			if (d == sh->pd_idx || d == sh->qd_idx)
@@ -4194,6 +4239,7 @@ static void make_discard_request(struct
 				goto again;
 			}
 		}
+		set_bit(STRIPE_DISCARD, &sh->state);
 		finish_wait(&conf->wait_for_overlap, &w);
 		for (d = 0; d < conf->raid_disks; d++) {
 			if (d == sh->pd_idx || d == sh->qd_idx)
diff -druNp linux-libre-3.8-gnu1/drivers/md/raid5.h linux-libre-3.8.13-gnu1/drivers/md/raid5.h
--- linux-libre-3.8-gnu1/drivers/md/raid5.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/md/raid5.h	2013-05-11 16:57:46.000000000 -0400
@@ -323,6 +323,7 @@ enum {
 	STRIPE_COMPUTE_RUN,
 	STRIPE_OPS_REQ_PENDING,
 	STRIPE_ON_UNPLUG_LIST,
+	STRIPE_DISCARD,
 };
 
 /*
diff -druNp linux-libre-3.8-gnu1/drivers/media/pci/bt8xx/bttv-driver.c linux-libre-3.8.13-gnu1/drivers/media/pci/bt8xx/bttv-driver.c
--- linux-libre-3.8-gnu1/drivers/media/pci/bt8xx/bttv-driver.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/pci/bt8xx/bttv-driver.c	2013-05-11 16:57:46.000000000 -0400
@@ -250,17 +250,19 @@ static u8 SRAM_Table[][60] =
    vdelay	start of active video in 2 * field lines relative to
 		trailing edge of /VRESET pulse (VDELAY register).
    sheight	height of active video in 2 * field lines.
+   extraheight	Added to sheight for cropcap.bounds.height only
    videostart0	ITU-R frame line number of the line corresponding
 		to vdelay in the first field. */
 #define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,	 \
-		vdelay, sheight, videostart0)				 \
+		vdelay, sheight, extraheight, videostart0)		 \
 	.cropcap.bounds.left = minhdelayx1,				 \
 	/* * 2 because vertically we count field lines times two, */	 \
 	/* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */		 \
 	.cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
 	/* 4 is a safety margin at the end of the line. */		 \
 	.cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,	 \
-	.cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,	 \
+	.cropcap.bounds.height = (sheight) + (extraheight) + (vdelay) -	 \
+				 MIN_VDELAY,				 \
 	.cropcap.defrect.left = hdelayx1,				 \
 	.cropcap.defrect.top = (videostart0) * 2,			 \
 	.cropcap.defrect.width = swidth,				 \
@@ -301,9 +303,10 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* totalwidth */ 1135,
 			/* sqwidth */ 944,
 			/* vdelay */ 0x20,
-		/* bt878 (and bt848?) can capture another
-		   line below active video. */
-			/* sheight */ (576 + 2) + 0x20 - 2,
+			/* sheight */ 576,
+			/* bt878 (and bt848?) can capture another
+			   line below active video. */
+			/* extraheight */ 2,
 			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
@@ -330,6 +333,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 780,
 			/* vdelay */ 0x1a,
 			/* sheight */ 480,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_SECAM,
@@ -355,6 +359,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 944,
 			/* vdelay */ 0x20,
 			/* sheight */ 576,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_PAL_Nc,
@@ -380,6 +385,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 780,
 			/* vdelay */ 0x1a,
 			/* sheight */ 576,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_PAL_M,
@@ -405,6 +411,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 780,
 			/* vdelay */ 0x1a,
 			/* sheight */ 480,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_PAL_N,
@@ -430,6 +437,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 944,
 			/* vdelay */ 0x20,
 			/* sheight */ 576,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_NTSC_M_JP,
@@ -455,6 +463,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 780,
 			/* vdelay */ 0x16,
 			/* sheight */ 480,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	},{
 		/* that one hopefully works with the strange timing
@@ -484,6 +493,7 @@ const struct bttv_tvnorm bttv_tvnorms[]
 			/* sqwidth */ 944,
 			/* vdelay */ 0x1a,
 			/* sheight */ 480,
+			/* extraheight */ 0,
 			/* videostart0 */ 23)
 	}
 };
diff -druNp linux-libre-3.8-gnu1/drivers/media/pci/cx18/cx18-alsa-main.c linux-libre-3.8.13-gnu1/drivers/media/pci/cx18/cx18-alsa-main.c
--- linux-libre-3.8-gnu1/drivers/media/pci/cx18/cx18-alsa-main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/pci/cx18/cx18-alsa-main.c	2013-05-11 16:57:46.000000000 -0400
@@ -197,7 +197,7 @@ err_exit:
 	return ret;
 }
 
-static int __init cx18_alsa_load(struct cx18 *cx)
+static int cx18_alsa_load(struct cx18 *cx)
 {
 	struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
 	struct cx18_stream *s;
diff -druNp linux-libre-3.8-gnu1/drivers/media/pci/cx18/cx18-alsa-pcm.h linux-libre-3.8.13-gnu1/drivers/media/pci/cx18/cx18-alsa-pcm.h
--- linux-libre-3.8-gnu1/drivers/media/pci/cx18/cx18-alsa-pcm.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/pci/cx18/cx18-alsa-pcm.h	2013-05-11 16:57:46.000000000 -0400
@@ -20,7 +20,7 @@
  *  02111-1307  USA
  */
 
-int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc);
+int snd_cx18_pcm_create(struct snd_cx18_card *cxsc);
 
 /* Used by cx18-mailbox to announce the PCM data to the module */
 void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data,
diff -druNp linux-libre-3.8-gnu1/drivers/media/pci/ivtv/ivtv-alsa-main.c linux-libre-3.8.13-gnu1/drivers/media/pci/ivtv/ivtv-alsa-main.c
--- linux-libre-3.8-gnu1/drivers/media/pci/ivtv/ivtv-alsa-main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/pci/ivtv/ivtv-alsa-main.c	2013-05-11 16:57:46.000000000 -0400
@@ -205,7 +205,7 @@ err_exit:
 	return ret;
 }
 
-static int __init ivtv_alsa_load(struct ivtv *itv)
+static int ivtv_alsa_load(struct ivtv *itv)
 {
 	struct v4l2_device *v4l2_dev = &itv->v4l2_dev;
 	struct ivtv_stream *s;
diff -druNp linux-libre-3.8-gnu1/drivers/media/pci/ivtv/ivtv-alsa-pcm.h linux-libre-3.8.13-gnu1/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
--- linux-libre-3.8-gnu1/drivers/media/pci/ivtv/ivtv-alsa-pcm.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/pci/ivtv/ivtv-alsa-pcm.h	2013-05-11 16:57:46.000000000 -0400
@@ -20,4 +20,4 @@
  *  02111-1307  USA
  */
 
-int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc);
+int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc);
diff -druNp linux-libre-3.8-gnu1/drivers/media/platform/omap/omap_vout.c linux-libre-3.8.13-gnu1/drivers/media/platform/omap/omap_vout.c
--- linux-libre-3.8-gnu1/drivers/media/platform/omap/omap_vout.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/platform/omap/omap_vout.c	2013-05-11 16:57:46.000000000 -0400
@@ -205,19 +205,21 @@ static u32 omap_vout_uservirt_to_phys(u3
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 
-	vma = find_vma(mm, virtp);
 	/* For kernel direct-mapped memory, take the easy way */
-	if (virtp >= PAGE_OFFSET) {
-		physp = virt_to_phys((void *) virtp);
-	} else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
+	if (virtp >= PAGE_OFFSET)
+		return virt_to_phys((void *) virtp);
+
+	down_read(&current->mm->mmap_sem);
+	vma = find_vma(mm, virtp);
+	if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
 		/* this will catch, kernel-allocated, mmaped-to-usermode
 		   addresses */
 		physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
+		up_read(&current->mm->mmap_sem);
 	} else {
 		/* otherwise, use get_user_pages() for general userland pages */
 		int res, nr_pages = 1;
 		struct page *pages;
-		down_read(&current->mm->mmap_sem);
 
 		res = get_user_pages(current, current->mm, virtp, nr_pages, 1,
 				0, &pages, NULL);
diff -druNp linux-libre-3.8-gnu1/drivers/media/rc/rc-main.c linux-libre-3.8.13-gnu1/drivers/media/rc/rc-main.c
--- linux-libre-3.8-gnu1/drivers/media/rc/rc-main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/rc/rc-main.c	2013-05-11 16:57:46.000000000 -0400
@@ -789,8 +789,10 @@ static ssize_t show_protocols(struct dev
 	} else if (dev->raw) {
 		enabled = dev->raw->enabled_protocols;
 		allowed = ir_raw_get_allowed_protocols();
-	} else
+	} else {
+		mutex_unlock(&dev->lock);
 		return -ENODEV;
+	}
 
 	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
 		   (long long)allowed,
diff -druNp linux-libre-3.8-gnu1/drivers/media/v4l2-core/v4l2-device.c linux-libre-3.8.13-gnu1/drivers/media/v4l2-core/v4l2-device.c
--- linux-libre-3.8-gnu1/drivers/media/v4l2-core/v4l2-device.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/media/v4l2-core/v4l2-device.c	2013-05-11 16:57:46.000000000 -0400
@@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v
 	sd->v4l2_dev = v4l2_dev;
 	if (sd->internal_ops && sd->internal_ops->registered) {
 		err = sd->internal_ops->registered(sd);
-		if (err) {
-			module_put(sd->owner);
-			return err;
-		}
+		if (err)
+			goto error_module;
 	}
 
 	/* This just returns 0 if either of the two args is NULL */
 	err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL);
-	if (err) {
-		if (sd->internal_ops && sd->internal_ops->unregistered)
-			sd->internal_ops->unregistered(sd);
-		module_put(sd->owner);
-		return err;
-	}
+	if (err)
+		goto error_unregister;
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	/* Register the entity. */
 	if (v4l2_dev->mdev) {
 		err = media_device_register_entity(v4l2_dev->mdev, entity);
-		if (err < 0) {
-			if (sd->internal_ops && sd->internal_ops->unregistered)
-				sd->internal_ops->unregistered(sd);
-			module_put(sd->owner);
-			return err;
-		}
+		if (err < 0)
+			goto error_unregister;
 	}
 #endif
 
@@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v
 	spin_unlock(&v4l2_dev->lock);
 
 	return 0;
+
+error_unregister:
+	if (sd->internal_ops && sd->internal_ops->unregistered)
+		sd->internal_ops->unregistered(sd);
+error_module:
+	module_put(sd->owner);
+	sd->v4l2_dev = NULL;
+	return err;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
 
diff -druNp linux-libre-3.8-gnu1/drivers/memstick/host/rtsx_pci_ms.c linux-libre-3.8.13-gnu1/drivers/memstick/host/rtsx_pci_ms.c
--- linux-libre-3.8-gnu1/drivers/memstick/host/rtsx_pci_ms.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/memstick/host/rtsx_pci_ms.c	2013-05-11 16:57:46.000000000 -0400
@@ -426,6 +426,9 @@ static void rtsx_pci_ms_request(struct m
 
 	dev_dbg(ms_dev(host), "--> %s\n", __func__);
 
+	if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD))
+		return;
+
 	schedule_work(&host->handle_req);
 }
 
@@ -441,6 +444,10 @@ static int rtsx_pci_ms_set_param(struct
 	dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
 			__func__, param, value);
 
+	err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD);
+	if (err)
+		return err;
+
 	switch (param) {
 	case MEMSTICK_POWER:
 		if (value == MEMSTICK_POWER_ON)
diff -druNp linux-libre-3.8-gnu1/drivers/mfd/adp5520.c linux-libre-3.8.13-gnu1/drivers/mfd/adp5520.c
--- linux-libre-3.8-gnu1/drivers/mfd/adp5520.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mfd/adp5520.c	2013-05-11 16:57:46.000000000 -0400
@@ -36,6 +36,7 @@ struct adp5520_chip {
 	struct blocking_notifier_head notifier_list;
 	int irq;
 	unsigned long id;
+	uint8_t mode;
 };
 
 static int __adp5520_read(struct i2c_client *client,
@@ -326,7 +327,10 @@ static int adp5520_suspend(struct device
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
 
-	adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
+	adp5520_read(chip->dev, ADP5520_MODE_STATUS, &chip->mode);
+	/* All other bits are W1C */
+	chip->mode &= ADP5520_BL_EN | ADP5520_DIM_EN | ADP5520_nSTNBY;
+	adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
 	return 0;
 }
 
@@ -335,7 +339,7 @@ static int adp5520_resume(struct device
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
 
-	adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
+	adp5520_write(chip->dev, ADP5520_MODE_STATUS, chip->mode);
 	return 0;
 }
 #endif
diff -druNp linux-libre-3.8-gnu1/drivers/mfd/rtsx_pcr.c linux-libre-3.8.13-gnu1/drivers/mfd/rtsx_pcr.c
--- linux-libre-3.8-gnu1/drivers/mfd/rtsx_pcr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mfd/rtsx_pcr.c	2013-05-11 16:57:46.000000000 -0400
@@ -713,6 +713,25 @@ int rtsx_pci_card_power_off(struct rtsx_
 }
 EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
 
+int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
+{
+	unsigned int cd_mask[] = {
+		[RTSX_SD_CARD] = SD_EXIST,
+		[RTSX_MS_CARD] = MS_EXIST
+	};
+
+	if (!pcr->ms_pmos) {
+		/* When using single PMOS, accessing card is not permitted
+		 * if the existing card is not the designated one.
+		 */
+		if (pcr->card_exist & (~cd_mask[card]))
+			return -EIO;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_exclusive_check);
+
 int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
 {
 	if (pcr->ops->switch_output_voltage)
@@ -758,7 +777,7 @@ static void rtsx_pci_card_detect(struct
 	struct delayed_work *dwork;
 	struct rtsx_pcr *pcr;
 	unsigned long flags;
-	unsigned int card_detect = 0;
+	unsigned int card_detect = 0, card_inserted, card_removed;
 	u32 irq_status;
 
 	dwork = to_delayed_work(work);
@@ -766,25 +785,35 @@ static void rtsx_pci_card_detect(struct
 
 	dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
 
+	mutex_lock(&pcr->pcr_mutex);
 	spin_lock_irqsave(&pcr->lock, flags);
 
 	irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
 	dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status);
 
-	if (pcr->card_inserted || pcr->card_removed) {
+	irq_status &= CARD_EXIST;
+	card_inserted = pcr->card_inserted & irq_status;
+	card_removed = pcr->card_removed;
+	pcr->card_inserted = 0;
+	pcr->card_removed = 0;
+
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	if (card_inserted || card_removed) {
 		dev_dbg(&(pcr->pci->dev),
 				"card_inserted: 0x%x, card_removed: 0x%x\n",
-				pcr->card_inserted, pcr->card_removed);
+				card_inserted, card_removed);
 
 		if (pcr->ops->cd_deglitch)
-			pcr->card_inserted = pcr->ops->cd_deglitch(pcr);
+			card_inserted = pcr->ops->cd_deglitch(pcr);
 
-		card_detect = pcr->card_inserted | pcr->card_removed;
-		pcr->card_inserted = 0;
-		pcr->card_removed = 0;
+		card_detect = card_inserted | card_removed;
+
+		pcr->card_exist |= card_inserted;
+		pcr->card_exist &= ~card_removed;
 	}
 
-	spin_unlock_irqrestore(&pcr->lock, flags);
+	mutex_unlock(&pcr->pcr_mutex);
 
 	if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event)
 		pcr->slots[RTSX_SD_CARD].card_event(
@@ -836,10 +865,6 @@ static irqreturn_t rtsx_pci_isr(int irq,
 		}
 	}
 
-	if (pcr->card_inserted || pcr->card_removed)
-		schedule_delayed_work(&pcr->carddet_work,
-				msecs_to_jiffies(200));
-
 	if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
 		if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
 			pcr->trans_result = TRANS_RESULT_FAIL;
@@ -852,6 +877,10 @@ static irqreturn_t rtsx_pci_isr(int irq,
 		}
 	}
 
+	if (pcr->card_inserted || pcr->card_removed)
+		schedule_delayed_work(&pcr->carddet_work,
+				msecs_to_jiffies(200));
+
 	spin_unlock(&pcr->lock);
 	return IRQ_HANDLED;
 }
@@ -974,6 +1003,14 @@ static int rtsx_pci_init_hw(struct rtsx_
 			return err;
 	}
 
+	/* No CD interrupt if probing driver with card inserted.
+	 * So we need to initialize pcr->card_exist here.
+	 */
+	if (pcr->ops->cd_deglitch)
+		pcr->card_exist = pcr->ops->cd_deglitch(pcr);
+	else
+		pcr->card_exist = rtsx_pci_readl(pcr, RTSX_BIPR) & CARD_EXIST;
+
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/mmc/core/mmc.c linux-libre-3.8.13-gnu1/drivers/mmc/core/mmc.c
--- linux-libre-3.8-gnu1/drivers/mmc/core/mmc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mmc/core/mmc.c	2013-05-11 16:57:46.000000000 -0400
@@ -368,13 +368,13 @@ static int mmc_read_ext_csd(struct mmc_c
 		ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
 	card->ext_csd.raw_trim_mult =
 		ext_csd[EXT_CSD_TRIM_MULT];
+	card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
 	if (card->ext_csd.rev >= 4) {
 		/*
 		 * Enhanced area feature support -- check whether the eMMC
 		 * card has the Enhanced area enabled.  If so, export enhanced
 		 * area offset and size to user by adding sysfs interface.
 		 */
-		card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
 		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
 		    (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
 			hc_erase_grp_sz =
@@ -496,7 +496,7 @@ static int mmc_read_ext_csd(struct mmc_c
 		 * RPMB regions are defined in multiples of 128K.
 		 */
 		card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
-		if (ext_csd[EXT_CSD_RPMB_MULT]) {
+		if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) {
 			mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
 				EXT_CSD_PART_CONFIG_ACC_RPMB,
 				"rpmb", 0, false,
diff -druNp linux-libre-3.8-gnu1/drivers/mmc/host/atmel-mci.c linux-libre-3.8.13-gnu1/drivers/mmc/host/atmel-mci.c
--- linux-libre-3.8-gnu1/drivers/mmc/host/atmel-mci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mmc/host/atmel-mci.c	2013-05-11 16:57:46.000000000 -0400
@@ -178,6 +178,7 @@ struct atmel_mci {
 	void __iomem		*regs;
 
 	struct scatterlist	*sg;
+	unsigned int		sg_len;
 	unsigned int		pio_offset;
 	unsigned int		*buffer;
 	unsigned int		buf_size;
@@ -892,6 +893,7 @@ static u32 atmci_prepare_data(struct atm
 	data->error = -EINPROGRESS;
 
 	host->sg = data->sg;
+	host->sg_len = data->sg_len;
 	host->data = data;
 	host->data_chan = NULL;
 
@@ -1826,7 +1828,8 @@ static void atmci_read_data_pio(struct a
 			if (offset == sg->length) {
 				flush_dcache_page(sg_page(sg));
 				host->sg = sg = sg_next(sg);
-				if (!sg)
+				host->sg_len--;
+				if (!sg || !host->sg_len)
 					goto done;
 
 				offset = 0;
@@ -1839,7 +1842,8 @@ static void atmci_read_data_pio(struct a
 
 			flush_dcache_page(sg_page(sg));
 			host->sg = sg = sg_next(sg);
-			if (!sg)
+			host->sg_len--;
+			if (!sg || !host->sg_len)
 				goto done;
 
 			offset = 4 - remaining;
@@ -1890,7 +1894,8 @@ static void atmci_write_data_pio(struct
 			nbytes += 4;
 			if (offset == sg->length) {
 				host->sg = sg = sg_next(sg);
-				if (!sg)
+				host->sg_len--;
+				if (!sg || !host->sg_len)
 					goto done;
 
 				offset = 0;
@@ -1904,7 +1909,8 @@ static void atmci_write_data_pio(struct
 			nbytes += remaining;
 
 			host->sg = sg = sg_next(sg);
-			if (!sg) {
+			host->sg_len--;
+			if (!sg || !host->sg_len) {
 				atmci_writel(host, ATMCI_TDR, value);
 				goto done;
 			}
@@ -2487,10 +2493,8 @@ static int __exit atmci_remove(struct pl
 	atmci_readl(host, ATMCI_SR);
 	clk_disable(host->mck);
 
-#ifdef CONFIG_MMC_ATMELMCI_DMA
 	if (host->dma.chan)
 		dma_release_channel(host->dma.chan);
-#endif
 
 	free_irq(platform_get_irq(pdev, 0), host);
 	iounmap(host->regs);
diff -druNp linux-libre-3.8-gnu1/drivers/mmc/host/Kconfig linux-libre-3.8.13-gnu1/drivers/mmc/host/Kconfig
--- linux-libre-3.8-gnu1/drivers/mmc/host/Kconfig	2013-05-01 16:47:35.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/mmc/host/Kconfig	2013-05-11 19:23:23.000000000 -0400
@@ -292,16 +292,6 @@ config MMC_ATMELMCI
 
 	  If unsure, say N.
 
-config MMC_ATMELMCI_DMA
-	bool "Atmel MCI DMA support"
-	depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
-	help
-	  Say Y here to have the Atmel MCI driver use a DMA engine to
-	  do data transfers and thus increase the throughput and
-	  reduce the CPU utilization.
-
-	  If unsure, say N.
-
 config MMC_MSM
 	tristate "Qualcomm SDCC Controller Support"
 	depends on MMC && ARCH_MSM
diff -druNp linux-libre-3.8-gnu1/drivers/mmc/host/rtsx_pci_sdmmc.c linux-libre-3.8.13-gnu1/drivers/mmc/host/rtsx_pci_sdmmc.c
--- linux-libre-3.8-gnu1/drivers/mmc/host/rtsx_pci_sdmmc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mmc/host/rtsx_pci_sdmmc.c	2013-05-11 16:57:46.000000000 -0400
@@ -678,12 +678,19 @@ static void sdmmc_request(struct mmc_hos
 	struct mmc_command *cmd = mrq->cmd;
 	struct mmc_data *data = mrq->data;
 	unsigned int data_size = 0;
+	int err;
 
 	if (host->eject) {
 		cmd->error = -ENOMEDIUM;
 		goto finish;
 	}
 
+	err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD);
+	if (err) {
+		cmd->error = err;
+		goto finish;
+	}
+
 	mutex_lock(&pcr->pcr_mutex);
 
 	rtsx_pci_start_run(pcr);
@@ -901,6 +908,9 @@ static void sdmmc_set_ios(struct mmc_hos
 	if (host->eject)
 		return;
 
+	if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD))
+		return;
+
 	mutex_lock(&pcr->pcr_mutex);
 
 	rtsx_pci_start_run(pcr);
@@ -1073,6 +1083,10 @@ static int sdmmc_switch_voltage(struct m
 	if (host->eject)
 		return -ENOMEDIUM;
 
+	err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD);
+	if (err)
+		return err;
+
 	mutex_lock(&pcr->pcr_mutex);
 
 	rtsx_pci_start_run(pcr);
@@ -1122,6 +1136,10 @@ static int sdmmc_execute_tuning(struct m
 	if (host->eject)
 		return -ENOMEDIUM;
 
+	err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD);
+	if (err)
+		return err;
+
 	mutex_lock(&pcr->pcr_mutex);
 
 	rtsx_pci_start_run(pcr);
diff -druNp linux-libre-3.8-gnu1/drivers/mmc/host/sdhci-esdhc-imx.c linux-libre-3.8.13-gnu1/drivers/mmc/host/sdhci-esdhc-imx.c
--- linux-libre-3.8-gnu1/drivers/mmc/host/sdhci-esdhc-imx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mmc/host/sdhci-esdhc-imx.c	2013-05-11 16:57:46.000000000 -0400
@@ -237,15 +237,18 @@ static void esdhc_writel_le(struct sdhci
 
 static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
 	if (unlikely(reg == SDHCI_HOST_VERSION)) {
-		u16 val = readw(host->ioaddr + (reg ^ 2));
-		/*
-		 * uSDHC supports SDHCI v3.0, but it's encoded as value
-		 * 0x3 in host controller version register, which violates
-		 * SDHCI_SPEC_300 definition.  Work it around here.
-		 */
-		if ((val & SDHCI_SPEC_VER_MASK) == 3)
-			return --val;
+		reg ^= 2;
+		if (is_imx6q_usdhc(imx_data)) {
+			/*
+			 * The usdhc register returns a wrong host version.
+			 * Correct it here.
+			 */
+			return SDHCI_SPEC_300;
+		}
 	}
 
 	return readw(host->ioaddr + reg);
diff -druNp linux-libre-3.8-gnu1/drivers/mtd/mtdchar.c linux-libre-3.8.13-gnu1/drivers/mtd/mtdchar.c
--- linux-libre-3.8-gnu1/drivers/mtd/mtdchar.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mtd/mtdchar.c	2013-05-11 16:57:46.000000000 -0400
@@ -1159,45 +1159,17 @@ static int mtdchar_mmap(struct file *fil
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
 	struct map_info *map = mtd->priv;
-	resource_size_t start, off;
-	unsigned long len, vma_len;
 
         /* This is broken because it assumes the MTD device is map-based
 	   and that mtd->priv is a valid struct map_info.  It should be
 	   replaced with something that uses the mtd_get_unmapped_area()
 	   operation properly. */
 	if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
-		off = get_vm_offset(vma);
-		start = map->phys;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
-		start &= PAGE_MASK;
-		vma_len = get_vm_size(vma);
-
-		/* Overflow in off+len? */
-		if (vma_len + off < off)
-			return -EINVAL;
-		/* Does it fit in the mapping? */
-		if (vma_len + off > len)
-			return -EINVAL;
-
-		off += start;
-		/* Did that overflow? */
-		if (off < start)
-			return -EINVAL;
-		if (set_vm_offset(vma, off) < 0)
-			return -EINVAL;
-		vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
-
 #ifdef pgprot_noncached
-		if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
+		if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
 			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 #endif
-		if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-				       vma->vm_end - vma->vm_start,
-				       vma->vm_page_prot))
-			return -EAGAIN;
-
-		return 0;
+		return vm_iomap_memory(vma, map->phys, map->size);
 	}
 	return -ENOSYS;
 #else
diff -druNp linux-libre-3.8-gnu1/drivers/mtd/nand/nand_base.c linux-libre-3.8.13-gnu1/drivers/mtd/nand/nand_base.c
--- linux-libre-3.8-gnu1/drivers/mtd/nand/nand_base.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mtd/nand/nand_base.c	2013-05-11 16:57:46.000000000 -0400
@@ -1527,6 +1527,14 @@ static int nand_do_read_ops(struct mtd_i
 					oobreadlen -= toread;
 				}
 			}
+
+			if (chip->options & NAND_NEED_READRDY) {
+				/* Apply delay or wait for ready/busy pin */
+				if (!chip->dev_ready)
+					udelay(chip->chip_delay);
+				else
+					nand_wait_ready(mtd);
+			}
 		} else {
 			memcpy(buf, chip->buffers->databuf + col, bytes);
 			buf += bytes;
@@ -1791,6 +1799,14 @@ static int nand_do_read_oob(struct mtd_i
 		len = min(len, readlen);
 		buf = nand_transfer_oob(chip, buf, ops, len);
 
+		if (chip->options & NAND_NEED_READRDY) {
+			/* Apply delay or wait for ready/busy pin */
+			if (!chip->dev_ready)
+				udelay(chip->chip_delay);
+			else
+				nand_wait_ready(mtd);
+		}
+
 		readlen -= len;
 		if (!readlen)
 			break;
diff -druNp linux-libre-3.8-gnu1/drivers/mtd/nand/nand_ids.c linux-libre-3.8.13-gnu1/drivers/mtd/nand/nand_ids.c
--- linux-libre-3.8-gnu1/drivers/mtd/nand/nand_ids.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/mtd/nand/nand_ids.c	2013-05-11 16:57:46.000000000 -0400
@@ -22,49 +22,51 @@
 *	512	512 Byte page size
 */
 struct nand_flash_dev nand_flash_ids[] = {
+#define SP_OPTIONS NAND_NEED_READRDY
+#define SP_OPTIONS16 (SP_OPTIONS | NAND_BUSWIDTH_16)
 
 #ifdef CONFIG_MTD_NAND_MUSEUM_IDS
-	{"NAND 1MiB 5V 8-bit",		0x6e, 256, 1, 0x1000, 0},
-	{"NAND 2MiB 5V 8-bit",		0x64, 256, 2, 0x1000, 0},
-	{"NAND 4MiB 5V 8-bit",		0x6b, 512, 4, 0x2000, 0},
-	{"NAND 1MiB 3,3V 8-bit",	0xe8, 256, 1, 0x1000, 0},
-	{"NAND 1MiB 3,3V 8-bit",	0xec, 256, 1, 0x1000, 0},
-	{"NAND 2MiB 3,3V 8-bit",	0xea, 256, 2, 0x1000, 0},
-	{"NAND 4MiB 3,3V 8-bit",	0xd5, 512, 4, 0x2000, 0},
-	{"NAND 4MiB 3,3V 8-bit",	0xe3, 512, 4, 0x2000, 0},
-	{"NAND 4MiB 3,3V 8-bit",	0xe5, 512, 4, 0x2000, 0},
-	{"NAND 8MiB 3,3V 8-bit",	0xd6, 512, 8, 0x2000, 0},
+	{"NAND 1MiB 5V 8-bit",		0x6e, 256, 1, 0x1000, SP_OPTIONS},
+	{"NAND 2MiB 5V 8-bit",		0x64, 256, 2, 0x1000, SP_OPTIONS},
+	{"NAND 4MiB 5V 8-bit",		0x6b, 512, 4, 0x2000, SP_OPTIONS},
+	{"NAND 1MiB 3,3V 8-bit",	0xe8, 256, 1, 0x1000, SP_OPTIONS},
+	{"NAND 1MiB 3,3V 8-bit",	0xec, 256, 1, 0x1000, SP_OPTIONS},
+	{"NAND 2MiB 3,3V 8-bit",	0xea, 256, 2, 0x1000, SP_OPTIONS},
+	{"NAND 4MiB 3,3V 8-bit",	0xd5, 512, 4, 0x2000, SP_OPTIONS},
+	{"NAND 4MiB 3,3V 8-bit",	0xe3, 512, 4, 0x2000, SP_OPTIONS},
+	{"NAND 4MiB 3,3V 8-bit",	0xe5, 512, 4, 0x2000, SP_OPTIONS},
+	{"NAND 8MiB 3,3V 8-bit",	0xd6, 512, 8, 0x2000, SP_OPTIONS},
 
-	{"NAND 8MiB 1,8V 8-bit",	0x39, 512, 8, 0x2000, 0},
-	{"NAND 8MiB 3,3V 8-bit",	0xe6, 512, 8, 0x2000, 0},
-	{"NAND 8MiB 1,8V 16-bit",	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-	{"NAND 8MiB 3,3V 16-bit",	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+	{"NAND 8MiB 1,8V 8-bit",	0x39, 512, 8, 0x2000, SP_OPTIONS},
+	{"NAND 8MiB 3,3V 8-bit",	0xe6, 512, 8, 0x2000, SP_OPTIONS},
+	{"NAND 8MiB 1,8V 16-bit",	0x49, 512, 8, 0x2000, SP_OPTIONS16},
+	{"NAND 8MiB 3,3V 16-bit",	0x59, 512, 8, 0x2000, SP_OPTIONS16},
 #endif
 
-	{"NAND 16MiB 1,8V 8-bit",	0x33, 512, 16, 0x4000, 0},
-	{"NAND 16MiB 3,3V 8-bit",	0x73, 512, 16, 0x4000, 0},
-	{"NAND 16MiB 1,8V 16-bit",	0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 16MiB 3,3V 16-bit",	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 16MiB 1,8V 8-bit",	0x33, 512, 16, 0x4000, SP_OPTIONS},
+	{"NAND 16MiB 3,3V 8-bit",	0x73, 512, 16, 0x4000, SP_OPTIONS},
+	{"NAND 16MiB 1,8V 16-bit",	0x43, 512, 16, 0x4000, SP_OPTIONS16},
+	{"NAND 16MiB 3,3V 16-bit",	0x53, 512, 16, 0x4000, SP_OPTIONS16},
 
-	{"NAND 32MiB 1,8V 8-bit",	0x35, 512, 32, 0x4000, 0},
-	{"NAND 32MiB 3,3V 8-bit",	0x75, 512, 32, 0x4000, 0},
-	{"NAND 32MiB 1,8V 16-bit",	0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 32MiB 3,3V 16-bit",	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 32MiB 1,8V 8-bit",	0x35, 512, 32, 0x4000, SP_OPTIONS},
+	{"NAND 32MiB 3,3V 8-bit",	0x75, 512, 32, 0x4000, SP_OPTIONS},
+	{"NAND 32MiB 1,8V 16-bit",	0x45, 512, 32, 0x4000, SP_OPTIONS16},
+	{"NAND 32MiB 3,3V 16-bit",	0x55, 512, 32, 0x4000, SP_OPTIONS16},
 
-	{"NAND 64MiB 1,8V 8-bit",	0x36, 512, 64, 0x4000, 0},
-	{"NAND 64MiB 3,3V 8-bit",	0x76, 512, 64, 0x4000, 0},
-	{"NAND 64MiB 1,8V 16-bit",	0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 64MiB 3,3V 16-bit",	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 64MiB 1,8V 8-bit",	0x36, 512, 64, 0x4000, SP_OPTIONS},
+	{"NAND 64MiB 3,3V 8-bit",	0x76, 512, 64, 0x4000, SP_OPTIONS},
+	{"NAND 64MiB 1,8V 16-bit",	0x46, 512, 64, 0x4000, SP_OPTIONS16},
+	{"NAND 64MiB 3,3V 16-bit",	0x56, 512, 64, 0x4000, SP_OPTIONS16},
 
-	{"NAND 128MiB 1,8V 8-bit",	0x78, 512, 128, 0x4000, 0},
-	{"NAND 128MiB 1,8V 8-bit",	0x39, 512, 128, 0x4000, 0},
-	{"NAND 128MiB 3,3V 8-bit",	0x79, 512, 128, 0x4000, 0},
-	{"NAND 128MiB 1,8V 16-bit",	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 128MiB 1,8V 16-bit",	0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 128MiB 3,3V 16-bit",	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 128MiB 3,3V 16-bit",	0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 128MiB 1,8V 8-bit",	0x78, 512, 128, 0x4000, SP_OPTIONS},
+	{"NAND 128MiB 1,8V 8-bit",	0x39, 512, 128, 0x4000, SP_OPTIONS},
+	{"NAND 128MiB 3,3V 8-bit",	0x79, 512, 128, 0x4000, SP_OPTIONS},
+	{"NAND 128MiB 1,8V 16-bit",	0x72, 512, 128, 0x4000, SP_OPTIONS16},
+	{"NAND 128MiB 1,8V 16-bit",	0x49, 512, 128, 0x4000, SP_OPTIONS16},
+	{"NAND 128MiB 3,3V 16-bit",	0x74, 512, 128, 0x4000, SP_OPTIONS16},
+	{"NAND 128MiB 3,3V 16-bit",	0x59, 512, 128, 0x4000, SP_OPTIONS16},
 
-	{"NAND 256MiB 3,3V 8-bit",	0x71, 512, 256, 0x4000, 0},
+	{"NAND 256MiB 3,3V 8-bit",	0x71, 512, 256, 0x4000, SP_OPTIONS},
 
 	/*
 	 * These are the new chips with large page size. The pagesize and the
diff -druNp linux-libre-3.8-gnu1/drivers/net/bonding/bond_main.c linux-libre-3.8.13-gnu1/drivers/net/bonding/bond_main.c
--- linux-libre-3.8-gnu1/drivers/net/bonding/bond_main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/bonding/bond_main.c	2013-05-11 16:57:46.000000000 -0400
@@ -1728,6 +1728,8 @@ int bond_enslave(struct net_device *bond
 
 	bond_compute_features(bond);
 
+	bond_update_speed_duplex(new_slave);
+
 	read_lock(&bond->lock);
 
 	new_slave->last_arp_rx = jiffies -
@@ -1780,8 +1782,6 @@ int bond_enslave(struct net_device *bond
 		new_slave->link == BOND_LINK_DOWN ? "DOWN" :
 			(new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
 
-	bond_update_speed_duplex(new_slave);
-
 	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
 		if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
@@ -1888,6 +1888,7 @@ err_detach:
 	write_unlock_bh(&bond->lock);
 
 err_close:
+	slave_dev->priv_flags &= ~IFF_BONDING;
 	dev_close(slave_dev);
 
 err_unset_master:
@@ -1943,7 +1944,6 @@ int bond_release(struct net_device *bond
 	}
 
 	block_netpoll_tx();
-	call_netdevice_notifiers(NETDEV_RELEASE, bond_dev);
 	write_lock_bh(&bond->lock);
 
 	slave = bond_get_slave_by_dev(bond, slave_dev);
@@ -1956,12 +1956,11 @@ int bond_release(struct net_device *bond
 		return -EINVAL;
 	}
 
+	write_unlock_bh(&bond->lock);
 	/* unregister rx_handler early so bond_handle_frame wouldn't be called
 	 * for this slave anymore.
 	 */
 	netdev_rx_handler_unregister(slave_dev);
-	write_unlock_bh(&bond->lock);
-	synchronize_net();
 	write_lock_bh(&bond->lock);
 
 	if (!bond->params.fail_over_mac) {
@@ -2047,8 +2046,10 @@ int bond_release(struct net_device *bond
 	write_unlock_bh(&bond->lock);
 	unblock_netpoll_tx();
 
-	if (bond->slave_cnt == 0)
+	if (bond->slave_cnt == 0) {
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+		call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
+	}
 
 	bond_compute_features(bond);
 	if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
@@ -2462,8 +2463,6 @@ static void bond_miimon_commit(struct bo
 				bond_set_backup_slave(slave);
 			}
 
-			bond_update_speed_duplex(slave);
-
 			pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
 				bond->dev->name, slave->dev->name,
 				slave->speed, slave->duplex ? "full" : "half");
@@ -3381,20 +3380,22 @@ static int bond_xmit_hash_policy_l2(stru
  */
 static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
 {
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-	struct iphdr *iph;
-	struct ipv6hdr *ipv6h;
+	const struct ethhdr *data;
+	const struct iphdr *iph;
+	const struct ipv6hdr *ipv6h;
 	u32 v6hash;
-	__be32 *s, *d;
+	const __be32 *s, *d;
 
 	if (skb->protocol == htons(ETH_P_IP) &&
-	    skb_network_header_len(skb) >= sizeof(*iph)) {
+	    pskb_network_may_pull(skb, sizeof(*iph))) {
 		iph = ip_hdr(skb);
+		data = (struct ethhdr *)skb->data;
 		return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
 			(data->h_dest[5] ^ data->h_source[5])) % count;
 	} else if (skb->protocol == htons(ETH_P_IPV6) &&
-		   skb_network_header_len(skb) >= sizeof(*ipv6h)) {
+		   pskb_network_may_pull(skb, sizeof(*ipv6h))) {
 		ipv6h = ipv6_hdr(skb);
+		data = (struct ethhdr *)skb->data;
 		s = &ipv6h->saddr.s6_addr32[0];
 		d = &ipv6h->daddr.s6_addr32[0];
 		v6hash = (s[1] ^ d[1]) ^ (s[2] ^ d[2]) ^ (s[3] ^ d[3]);
@@ -3413,33 +3414,36 @@ static int bond_xmit_hash_policy_l23(str
 static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
 {
 	u32 layer4_xor = 0;
-	struct iphdr *iph;
-	struct ipv6hdr *ipv6h;
-	__be32 *s, *d;
-	__be16 *layer4hdr;
+	const struct iphdr *iph;
+	const struct ipv6hdr *ipv6h;
+	const __be32 *s, *d;
+	const __be16 *l4 = NULL;
+	__be16 _l4[2];
+	int noff = skb_network_offset(skb);
+	int poff;
 
 	if (skb->protocol == htons(ETH_P_IP) &&
-	    skb_network_header_len(skb) >= sizeof(*iph)) {
+	    pskb_may_pull(skb, noff + sizeof(*iph))) {
 		iph = ip_hdr(skb);
-		if (!ip_is_fragment(iph) &&
-		    (iph->protocol == IPPROTO_TCP ||
-		     iph->protocol == IPPROTO_UDP) &&
-		    (skb_headlen(skb) - skb_network_offset(skb) >=
-		     iph->ihl * sizeof(u32) + sizeof(*layer4hdr) * 2)) {
-			layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
-			layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
+		poff = proto_ports_offset(iph->protocol);
+
+		if (!ip_is_fragment(iph) && poff >= 0) {
+			l4 = skb_header_pointer(skb, noff + (iph->ihl << 2) + poff,
+						sizeof(_l4), &_l4);
+			if (l4)
+				layer4_xor = ntohs(l4[0] ^ l4[1]);
 		}
 		return (layer4_xor ^
 			((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
 	} else if (skb->protocol == htons(ETH_P_IPV6) &&
-		   skb_network_header_len(skb) >= sizeof(*ipv6h)) {
+		   pskb_may_pull(skb, noff + sizeof(*ipv6h))) {
 		ipv6h = ipv6_hdr(skb);
-		if ((ipv6h->nexthdr == IPPROTO_TCP ||
-		     ipv6h->nexthdr == IPPROTO_UDP) &&
-		    (skb_headlen(skb) - skb_network_offset(skb) >=
-		     sizeof(*ipv6h) + sizeof(*layer4hdr) * 2)) {
-			layer4hdr = (__be16 *)(ipv6h + 1);
-			layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
+		poff = proto_ports_offset(ipv6h->nexthdr);
+		if (poff >= 0) {
+			l4 = skb_header_pointer(skb, noff + sizeof(*ipv6h) + poff,
+						sizeof(_l4), &_l4);
+			if (l4)
+				layer4_xor = ntohs(l4[0] ^ l4[1]);
 		}
 		s = &ipv6h->saddr.s6_addr32[0];
 		d = &ipv6h->daddr.s6_addr32[0];
@@ -4921,9 +4925,18 @@ static int __net_init bond_net_init(stru
 static void __net_exit bond_net_exit(struct net *net)
 {
 	struct bond_net *bn = net_generic(net, bond_net_id);
+	struct bonding *bond, *tmp_bond;
+	LIST_HEAD(list);
 
 	bond_destroy_sysfs(bn);
 	bond_destroy_proc_dir(bn);
+
+	/* Kill off any bonds created after unregistering bond rtnl ops */
+	rtnl_lock();
+	list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list)
+		unregister_netdevice_queue(bond->dev, &list);
+	unregister_netdevice_many(&list);
+	rtnl_unlock();
 }
 
 static struct pernet_operations bond_net_ops = {
diff -druNp linux-libre-3.8-gnu1/drivers/net/bonding/bond_sysfs.c linux-libre-3.8.13-gnu1/drivers/net/bonding/bond_sysfs.c
--- linux-libre-3.8-gnu1/drivers/net/bonding/bond_sysfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/bonding/bond_sysfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -183,6 +183,11 @@ int bond_create_slave_symlinks(struct ne
 	sprintf(linkname, "slave_%s", slave->name);
 	ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
 				linkname);
+
+	/* free the master link created earlier in case of error */
+	if (ret)
+		sysfs_remove_link(&(slave->dev.kobj), "master");
+
 	return ret;
 
 }
@@ -522,7 +527,7 @@ static ssize_t bonding_store_arp_interva
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+		pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n",
 		       bond->dev->name, new_value, INT_MAX);
 		ret = -EINVAL;
 		goto out;
@@ -537,14 +542,15 @@ static ssize_t bonding_store_arp_interva
 	pr_info("%s: Setting ARP monitoring interval to %d.\n",
 		bond->dev->name, new_value);
 	bond->params.arp_interval = new_value;
-	if (bond->params.miimon) {
-		pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
-			bond->dev->name, bond->dev->name);
-		bond->params.miimon = 0;
-	}
-	if (!bond->params.arp_targets[0]) {
-		pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
-			bond->dev->name);
+	if (new_value) {
+		if (bond->params.miimon) {
+			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+				bond->dev->name, bond->dev->name);
+			bond->params.miimon = 0;
+		}
+		if (!bond->params.arp_targets[0])
+			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+				bond->dev->name);
 	}
 	if (bond->dev->flags & IFF_UP) {
 		/* If the interface is up, we may need to fire off
@@ -552,10 +558,13 @@ static ssize_t bonding_store_arp_interva
 		 * timer will get fired off when the open function
 		 * is called.
 		 */
-		cancel_delayed_work_sync(&bond->mii_work);
-		queue_delayed_work(bond->wq, &bond->arp_work, 0);
+		if (!new_value) {
+			cancel_delayed_work_sync(&bond->arp_work);
+		} else {
+			cancel_delayed_work_sync(&bond->mii_work);
+			queue_delayed_work(bond->wq, &bond->arp_work, 0);
+		}
 	}
-
 out:
 	rtnl_unlock();
 	return ret;
@@ -697,7 +706,7 @@ static ssize_t bonding_store_downdelay(s
 	}
 	if (new_value < 0) {
 		pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-		       bond->dev->name, new_value, 1, INT_MAX);
+		       bond->dev->name, new_value, 0, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
@@ -752,8 +761,8 @@ static ssize_t bonding_store_updelay(str
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-		       bond->dev->name, new_value, 1, INT_MAX);
+		pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n",
+		       bond->dev->name, new_value, 0, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
@@ -963,37 +972,37 @@ static ssize_t bonding_store_miimon(stru
 	}
 	if (new_value < 0) {
 		pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
-		       bond->dev->name, new_value, 1, INT_MAX);
+		       bond->dev->name, new_value, 0, INT_MAX);
 		ret = -EINVAL;
 		goto out;
-	} else {
-		pr_info("%s: Setting MII monitoring interval to %d.\n",
-			bond->dev->name, new_value);
-		bond->params.miimon = new_value;
-		if (bond->params.updelay)
-			pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
-				bond->dev->name,
-				bond->params.updelay * bond->params.miimon);
-		if (bond->params.downdelay)
-			pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
-				bond->dev->name,
-				bond->params.downdelay * bond->params.miimon);
-		if (bond->params.arp_interval) {
-			pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
-				bond->dev->name);
-			bond->params.arp_interval = 0;
-			if (bond->params.arp_validate) {
-				bond->params.arp_validate =
-					BOND_ARP_VALIDATE_NONE;
-			}
-		}
-
-		if (bond->dev->flags & IFF_UP) {
-			/* If the interface is up, we may need to fire off
-			 * the MII timer. If the interface is down, the
-			 * timer will get fired off when the open function
-			 * is called.
-			 */
+	}
+	pr_info("%s: Setting MII monitoring interval to %d.\n",
+		bond->dev->name, new_value);
+	bond->params.miimon = new_value;
+	if (bond->params.updelay)
+		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+			bond->dev->name,
+			bond->params.updelay * bond->params.miimon);
+	if (bond->params.downdelay)
+		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+			bond->dev->name,
+			bond->params.downdelay * bond->params.miimon);
+	if (new_value && bond->params.arp_interval) {
+		pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+			bond->dev->name);
+		bond->params.arp_interval = 0;
+		if (bond->params.arp_validate)
+			bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+	}
+	if (bond->dev->flags & IFF_UP) {
+		/* If the interface is up, we may need to fire off
+		 * the MII timer. If the interface is down, the
+		 * timer will get fired off when the open function
+		 * is called.
+		 */
+		if (!new_value) {
+			cancel_delayed_work_sync(&bond->mii_work);
+		} else {
 			cancel_delayed_work_sync(&bond->arp_work);
 			queue_delayed_work(bond->wq, &bond->mii_work, 0);
 		}
diff -druNp linux-libre-3.8-gnu1/drivers/net/can/mcp251x.c linux-libre-3.8.13-gnu1/drivers/net/can/mcp251x.c
--- linux-libre-3.8-gnu1/drivers/net/can/mcp251x.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/can/mcp251x.c	2013-05-11 16:57:46.000000000 -0400
@@ -922,6 +922,7 @@ static int mcp251x_open(struct net_devic
 	struct mcp251x_priv *priv = netdev_priv(net);
 	struct spi_device *spi = priv->spi;
 	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+	unsigned long flags;
 	int ret;
 
 	ret = open_candev(net);
@@ -938,9 +939,14 @@ static int mcp251x_open(struct net_devic
 	priv->tx_skb = NULL;
 	priv->tx_len = 0;
 
+	flags = IRQF_ONESHOT;
+	if (pdata->irq_flags)
+		flags |= pdata->irq_flags;
+	else
+		flags |= IRQF_TRIGGER_FALLING;
+
 	ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
-		  pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
-		  DEVICE_NAME, priv);
+				   flags, DEVICE_NAME, priv);
 	if (ret) {
 		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
 		if (pdata->transceiver_enable)
diff -druNp linux-libre-3.8-gnu1/drivers/net/can/sja1000/plx_pci.c linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/plx_pci.c
--- linux-libre-3.8-gnu1/drivers/net/can/sja1000/plx_pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/plx_pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -348,7 +348,7 @@ static inline int plx_pci_check_sja1000(
 	 */
 	if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
 	    REG_CR_BASICCAN_INITIAL &&
-	    (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
+	    (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) &&
 	    (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
 		flag = 1;
 
@@ -360,7 +360,7 @@ static inline int plx_pci_check_sja1000(
 	 * See states on p. 23 of the Datasheet.
 	 */
 	if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
-	    priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
+	    priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL &&
 	    priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
 		return flag;
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/can/sja1000/sja1000.c linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/sja1000.c
--- linux-libre-3.8-gnu1/drivers/net/can/sja1000/sja1000.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/sja1000.c	2013-05-11 16:57:46.000000000 -0400
@@ -91,7 +91,7 @@ static void sja1000_write_cmdreg(struct
 	 */
 	spin_lock_irqsave(&priv->cmdreg_lock, flags);
 	priv->write_reg(priv, REG_CMR, val);
-	priv->read_reg(priv, REG_SR);
+	priv->read_reg(priv, SJA1000_REG_SR);
 	spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
 }
 
@@ -499,7 +499,7 @@ irqreturn_t sja1000_interrupt(int irq, v
 
 	while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
 		n++;
-		status = priv->read_reg(priv, REG_SR);
+		status = priv->read_reg(priv, SJA1000_REG_SR);
 		/* check for absent controller due to hw unplug */
 		if (status == 0xFF && sja1000_is_absent(priv))
 			return IRQ_NONE;
@@ -526,7 +526,7 @@ irqreturn_t sja1000_interrupt(int irq, v
 			/* receive interrupt */
 			while (status & SR_RBS) {
 				sja1000_rx(dev);
-				status = priv->read_reg(priv, REG_SR);
+				status = priv->read_reg(priv, SJA1000_REG_SR);
 				/* check for absent controller */
 				if (status == 0xFF && sja1000_is_absent(priv))
 					return IRQ_NONE;
diff -druNp linux-libre-3.8-gnu1/drivers/net/can/sja1000/sja1000.h linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/sja1000.h
--- linux-libre-3.8-gnu1/drivers/net/can/sja1000/sja1000.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/sja1000.h	2013-05-11 16:57:46.000000000 -0400
@@ -56,7 +56,7 @@
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD		0x00
 #define REG_CMR		0x01
-#define REG_SR		0x02
+#define SJA1000_REG_SR		0x02
 #define REG_IR		0x03
 #define REG_IER		0x04
 #define REG_ALC		0x0B
diff -druNp linux-libre-3.8-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c
--- linux-libre-3.8-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c	2013-05-11 16:57:46.000000000 -0400
@@ -96,8 +96,8 @@ static int sja1000_ofp_probe(struct plat
 	struct net_device *dev;
 	struct sja1000_priv *priv;
 	struct resource res;
-	const u32 *prop;
-	int err, irq, res_size, prop_size;
+	u32 prop;
+	int err, irq, res_size;
 	void __iomem *base;
 
 	err = of_address_to_resource(np, 0, &res);
@@ -138,27 +138,27 @@ static int sja1000_ofp_probe(struct plat
 	priv->read_reg = sja1000_ofp_read_reg;
 	priv->write_reg = sja1000_ofp_write_reg;
 
-	prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
-	if (prop && (prop_size ==  sizeof(u32)))
-		priv->can.clock.freq = *prop / 2;
+	err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
+	if (!err)
+		priv->can.clock.freq = prop / 2;
 	else
 		priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
 
-	prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
-	if (prop && (prop_size == sizeof(u32)))
-		priv->ocr |= *prop & OCR_MODE_MASK;
+	err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
+	if (!err)
+		priv->ocr |= prop & OCR_MODE_MASK;
 	else
 		priv->ocr |= OCR_MODE_NORMAL; /* default */
 
-	prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
-	if (prop && (prop_size == sizeof(u32)))
-		priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+	err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
+	if (!err)
+		priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
 	else
 		priv->ocr |= OCR_TX0_PULLDOWN; /* default */
 
-	prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
-	if (prop && (prop_size == sizeof(u32)) && *prop) {
-		u32 divider = priv->can.clock.freq * 2 / *prop;
+	err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
+	if (!err && prop) {
+		u32 divider = priv->can.clock.freq * 2 / prop;
 
 		if (divider > 1)
 			priv->cdr |= divider / 2 - 1;
@@ -168,8 +168,7 @@ static int sja1000_ofp_probe(struct plat
 		priv->cdr |= CDR_CLK_OFF; /* default */
 	}
 
-	prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
-	if (!prop)
+	if (!of_property_read_bool(np, "nxp,no-comparator-bypass"))
 		priv->cdr |= CDR_CBP; /* default */
 
 	priv->irq_flags = IRQF_SHARED;
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2013-05-11 16:57:46.000000000 -0400
@@ -2075,7 +2075,7 @@ static int atl1c_tx_map(struct atl1c_ada
 		if (unlikely(pci_dma_mapping_error(adapter->pdev,
 						   buffer_info->dma)))
 			goto err_dma;
-
+		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
 		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
 			ATL1C_PCIMAP_TODEVICE);
 		mapped_len += map_len;
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e.h	2013-05-11 16:57:46.000000000 -0400
@@ -186,7 +186,7 @@ struct atl1e_tpd_desc {
 /* how about 0x2000 */
 #define MAX_TX_BUF_LEN      0x2000
 #define MAX_TX_BUF_SHIFT    13
-/*#define MAX_TX_BUF_LEN  0x3000 */
+#define MAX_TSO_SEG_SIZE    0x3c00
 
 /* rrs word 1 bit 0:31 */
 #define RRS_RX_CSUM_MASK	0xFFFF
@@ -438,7 +438,6 @@ struct atl1e_adapter {
 	struct atl1e_hw        hw;
 	struct atl1e_hw_stats  hw_stats;
 
-	bool have_msi;
 	u32 wol;
 	u16 link_speed;
 	u16 link_duplex;
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2013-05-11 16:57:46.000000000 -0400
@@ -1851,34 +1851,19 @@ static void atl1e_free_irq(struct atl1e_
 	struct net_device *netdev = adapter->netdev;
 
 	free_irq(adapter->pdev->irq, netdev);
-
-	if (adapter->have_msi)
-		pci_disable_msi(adapter->pdev);
 }
 
 static int atl1e_request_irq(struct atl1e_adapter *adapter)
 {
 	struct pci_dev    *pdev   = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
-	int flags = 0;
 	int err = 0;
 
-	adapter->have_msi = true;
-	err = pci_enable_msi(pdev);
-	if (err) {
-		netdev_dbg(netdev,
-			   "Unable to allocate MSI interrupt Error: %d\n", err);
-		adapter->have_msi = false;
-	}
-
-	if (!adapter->have_msi)
-		flags |= IRQF_SHARED;
-	err = request_irq(pdev->irq, atl1e_intr, flags, netdev->name, netdev);
+	err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name,
+			  netdev);
 	if (err) {
 		netdev_dbg(adapter->netdev,
 			   "Unable to allocate interrupt Error: %d\n", err);
-		if (adapter->have_msi)
-			pci_disable_msi(pdev);
 		return err;
 	}
 	netdev_dbg(netdev, "atl1e_request_irq OK\n");
@@ -2347,6 +2332,7 @@ static int atl1e_probe(struct pci_dev *p
 
 	INIT_WORK(&adapter->reset_task, atl1e_reset_task);
 	INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
+	netif_set_gso_max_size(netdev, MAX_TSO_SEG_SIZE);
 	err = register_netdev(netdev);
 	if (err) {
 		netdev_err(netdev, "register netdevice failed\n");
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c	2013-05-01 16:42:00.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c	2013-05-11 19:17:52.000000000 -0400
@@ -2522,6 +2522,7 @@ load_error2:
 	bp->port.pmf = 0;
 load_error1:
 	bnx2x_napi_disable(bp);
+	bnx2x_del_all_napi(bp);
 	/* clear pf_load status, as it was already set */
 	bnx2x_clear_pf_load(bp);
 load_error0:
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h	2013-05-11 16:57:46.000000000 -0400
@@ -456,8 +456,9 @@ struct bnx2x_fw_port_stats_old {
 
 #define UPDATE_QSTAT(s, t) \
 	do { \
-		qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \
 		qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \
+		qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi) \
+			+ ((qstats->t##_lo < qstats_old->t##_lo) ? 1 : 0); \
 	} while (0)
 
 #define UPDATE_QSTAT_OLD(f) \
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/tg3.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/tg3.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/tg3.c	2013-05-01 16:43:03.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/tg3.c	2013-05-11 19:18:55.000000000 -0400
@@ -321,6 +321,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_t
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57766)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -1834,6 +1835,8 @@ static void tg3_link_report(struct tg3 *
 
 		tg3_ump_link_report(tp);
 	}
+
+	tp->link_up = netif_carrier_ok(tp->dev);
 }
 
 static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
@@ -2487,12 +2490,6 @@ static int tg3_phy_reset_5703_4_5(struct
 	return err;
 }
 
-static void tg3_carrier_on(struct tg3 *tp)
-{
-	netif_carrier_on(tp->dev);
-	tp->link_up = true;
-}
-
 static void tg3_carrier_off(struct tg3 *tp)
 {
 	netif_carrier_off(tp->dev);
@@ -2518,7 +2515,7 @@ static int tg3_phy_reset(struct tg3 *tp)
 		return -EBUSY;
 
 	if (netif_running(tp->dev) && tp->link_up) {
-		tg3_carrier_off(tp);
+		netif_carrier_off(tp->dev);
 		tg3_link_report(tp);
 	}
 
@@ -4088,6 +4085,14 @@ static void tg3_phy_copper_begin(struct
 		tp->link_config.active_speed = tp->link_config.speed;
 		tp->link_config.active_duplex = tp->link_config.duplex;
 
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+			/* With autoneg disabled, 5715 only links up when the
+			 * advertisement register has the configured speed
+			 * enabled.
+			 */
+			tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL);
+		}
+
 		bmcr = 0;
 		switch (tp->link_config.speed) {
 		default:
@@ -4216,9 +4221,9 @@ static bool tg3_test_and_report_link_chg
 {
 	if (curr_link_up != tp->link_up) {
 		if (curr_link_up) {
-			tg3_carrier_on(tp);
+			netif_carrier_on(tp->dev);
 		} else {
-			tg3_carrier_off(tp);
+			netif_carrier_off(tp->dev);
 			if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
 				tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
 		}
@@ -9090,7 +9095,14 @@ static int tg3_reset_hw(struct tg3 *tp,
 		}
 
 		if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) {
-			u32 grc_mode = tr32(GRC_MODE);
+			u32 grc_mode;
+
+			/* Fix transmit hangs */
+			val = tr32(TG3_CPMU_PADRNG_CTL);
+			val |= TG3_CPMU_PADRNG_CTL_RDIV2;
+			tw32(TG3_CPMU_PADRNG_CTL, val);
+
+			grc_mode = tr32(GRC_MODE);
 
 			/* Access the lower 1K of DL PCIE block registers. */
 			val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
@@ -9400,6 +9412,14 @@ static int tg3_reset_hw(struct tg3 *tp,
 	if (tg3_flag(tp, PCI_EXPRESS))
 		rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) {
+		tp->dma_limit = 0;
+		if (tp->dev->mtu <= ETH_DATA_LEN) {
+			rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR;
+			tp->dma_limit = TG3_TX_BD_DMA_MAX_2K;
+		}
+	}
+
 	if (tg3_flag(tp, HW_TSO_1) ||
 	    tg3_flag(tp, HW_TSO_2) ||
 	    tg3_flag(tp, HW_TSO_3))
@@ -14390,8 +14410,11 @@ static void tg3_read_vpd(struct tg3 *tp)
 		if (j + len > block_end)
 			goto partno;
 
-		memcpy(tp->fw_ver, &vpd_data[j], len);
-		strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
+		if (len >= sizeof(tp->fw_ver))
+			len = sizeof(tp->fw_ver) - 1;
+		memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
+		snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
+			 &vpd_data[j]);
 	}
 
 partno:
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/tg3.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/tg3.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/broadcom/tg3.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/broadcom/tg3.h	2013-05-11 16:57:46.000000000 -0400
@@ -1159,6 +1159,8 @@
 #define  CPMU_MUTEX_GNT_DRIVER		 0x00001000
 #define TG3_CPMU_PHY_STRAP		0x00003664
 #define TG3_CPMU_PHY_STRAP_IS_SERDES	 0x00000020
+#define TG3_CPMU_PADRNG_CTL		0x00003668
+#define  TG3_CPMU_PADRNG_CTL_RDIV2	 0x00040000
 /* 0x3664 --> 0x36b0 unused */
 
 #define TG3_CPMU_EEE_MODE		0x000036b0
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/davicom/dm9000.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/davicom/dm9000.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/davicom/dm9000.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/davicom/dm9000.c	2013-05-11 16:57:46.000000000 -0400
@@ -257,6 +257,107 @@ static void dm9000_dumpblk_32bit(void __
 		tmp = readl(reg);
 }
 
+/*
+ * Sleep, either by using msleep() or if we are suspending, then
+ * use mdelay() to sleep.
+ */
+static void dm9000_msleep(board_info_t *db, unsigned int ms)
+{
+	if (db->in_suspend)
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+/* Read a word from phyxcer */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+	board_info_t *db = netdev_priv(dev);
+	unsigned long flags;
+	unsigned int reg_save;
+	int ret;
+
+	mutex_lock(&db->addr_lock);
+
+	spin_lock_irqsave(&db->lock, flags);
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
+	/* Fill the phyxcer register into REG_0C */
+	iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+	/* Issue phyxcer read command */
+	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);
+
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_msleep(db, 1);		/* Wait read complete */
+
+	spin_lock_irqsave(&db->lock, flags);
+	reg_save = readb(db->io_addr);
+
+	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
+
+	/* The read data keeps on REG_0D & REG_0E */
+	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+	/* restore the previous address */
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	mutex_unlock(&db->addr_lock);
+
+	dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
+	return ret;
+}
+
+/* Write a word to phyxcer */
+static void
+dm9000_phy_write(struct net_device *dev,
+		 int phyaddr_unused, int reg, int value)
+{
+	board_info_t *db = netdev_priv(dev);
+	unsigned long flags;
+	unsigned long reg_save;
+
+	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
+	mutex_lock(&db->addr_lock);
+
+	spin_lock_irqsave(&db->lock, flags);
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
+	/* Fill the phyxcer register into REG_0C */
+	iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+	/* Fill the written data into REG_0D & REG_0E */
+	iow(db, DM9000_EPDRL, value);
+	iow(db, DM9000_EPDRH, value >> 8);
+
+	/* Issue phyxcer write command */
+	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
+
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_msleep(db, 1);		/* Wait write complete */
+
+	spin_lock_irqsave(&db->lock, flags);
+	reg_save = readb(db->io_addr);
+
+	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
+
+	/* restore the previous address */
+	writeb(reg_save, db->io_addr);
+
+	spin_unlock_irqrestore(&db->lock, flags);
+	mutex_unlock(&db->addr_lock);
+}
+
 /* dm9000_set_io
  *
  * select the specified set of io routines to use with the
@@ -794,6 +895,9 @@ dm9000_init_dm9000(struct net_device *de
 
 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
 
+	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+	dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+
 	ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
 	/* if wol is needed, then always set NCR_WAKEEN otherwise we end
@@ -1200,109 +1304,6 @@ dm9000_open(struct net_device *dev)
 	return 0;
 }
 
-/*
- * Sleep, either by using msleep() or if we are suspending, then
- * use mdelay() to sleep.
- */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
-{
-	if (db->in_suspend)
-		mdelay(ms);
-	else
-		msleep(ms);
-}
-
-/*
- *   Read a word from phyxcer
- */
-static int
-dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned int reg_save;
-	int ret;
-
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock,flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Fill the phyxcer register into REG_0C */
-	iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);	/* Issue phyxcer read command */
-
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock,flags);
-
-	dm9000_msleep(db, 1);		/* Wait read complete */
-
-	spin_lock_irqsave(&db->lock,flags);
-	reg_save = readb(db->io_addr);
-
-	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
-
-	/* The read data keeps on REG_0D & REG_0E */
-	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
-
-	/* restore the previous address */
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock,flags);
-
-	mutex_unlock(&db->addr_lock);
-
-	dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
-	return ret;
-}
-
-/*
- *   Write a word to phyxcer
- */
-static void
-dm9000_phy_write(struct net_device *dev,
-		 int phyaddr_unused, int reg, int value)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned long reg_save;
-
-	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock,flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Fill the phyxcer register into REG_0C */
-	iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-	/* Fill the written data into REG_0D & REG_0E */
-	iow(db, DM9000_EPDRL, value);
-	iow(db, DM9000_EPDRH, value >> 8);
-
-	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);	/* Issue phyxcer write command */
-
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	dm9000_msleep(db, 1);		/* Wait write complete */
-
-	spin_lock_irqsave(&db->lock,flags);
-	reg_save = readb(db->io_addr);
-
-	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
-
-	/* restore the previous address */
-	writeb(reg_save, db->io_addr);
-
-	spin_unlock_irqrestore(&db->lock, flags);
-	mutex_unlock(&db->addr_lock);
-}
-
 static void
 dm9000_shutdown(struct net_device *dev)
 {
@@ -1501,7 +1502,12 @@ dm9000_probe(struct platform_device *pde
 	db->flags |= DM9000_PLATF_SIMPLE_PHY;
 #endif
 
-	dm9000_reset(db);
+	/* Fixing bug on dm9000_probe, takeover dm9000_reset(db),
+	 * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo
+	 * while probe stage.
+	 */
+
+	iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST);
 
 	/* try multiple times, DM9000 sometimes gets the read wrong */
 	for (i = 0; i < 8; i++) {
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/davicom/dm9000.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/davicom/dm9000.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/davicom/dm9000.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/davicom/dm9000.h	2013-05-11 16:57:46.000000000 -0400
@@ -69,7 +69,9 @@
 #define NCR_WAKEEN          (1<<6)
 #define NCR_FCOL            (1<<4)
 #define NCR_FDX             (1<<3)
-#define NCR_LBK             (3<<1)
+
+#define NCR_RESERVED        (3<<1)
+#define NCR_MAC_LBK         (1<<1)
 #define NCR_RST	            (1<<0)
 
 #define NSR_SPEED           (1<<7)
@@ -167,5 +169,12 @@
 #define ISR_LNKCHNG		(1<<5)
 #define ISR_UNDERRUN		(1<<4)
 
+/* Davicom MII registers.
+ */
+
+#define MII_DM_DSPCR		0x1b    /* DSP Control Register */
+
+#define DSPCR_INIT_PARAM	0xE100	/* DSP init parameter */
+
 #endif /* _DM9000X_H_ */
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/freescale/fec_ptp.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/freescale/fec_ptp.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/freescale/fec_ptp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/freescale/fec_ptp.c	2013-05-11 16:57:46.000000000 -0400
@@ -128,6 +128,7 @@ void fec_ptp_start_cyclecounter(struct n
 
 	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 }
+EXPORT_SYMBOL(fec_ptp_start_cyclecounter);
 
 /**
  * fec_ptp_adjfreq - adjust ptp cycle frequency
@@ -318,6 +319,7 @@ int fec_ptp_ioctl(struct net_device *nde
 	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
 	    -EFAULT : 0;
 }
+EXPORT_SYMBOL(fec_ptp_ioctl);
 
 /**
  * fec_time_keep - call timecounter_read every second to avoid timer overrun
@@ -381,3 +383,4 @@ void fec_ptp_init(struct net_device *nde
 		pr_info("registered PHC device on %s\n", ndev->name);
 	}
 }
+EXPORT_SYMBOL(fec_ptp_init);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/freescale/gianfar_ptp.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/freescale/gianfar_ptp.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/freescale/gianfar_ptp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/freescale/gianfar_ptp.c	2013-05-11 16:57:46.000000000 -0400
@@ -127,7 +127,6 @@ struct gianfar_ptp_registers {
 
 #define DRIVER		"gianfar_ptp"
 #define DEFAULT_CKSEL	1
-#define N_ALARM		1 /* first alarm is used internally to reset fipers */
 #define N_EXT_TS	2
 #define REG_SIZE	sizeof(struct gianfar_ptp_registers)
 
@@ -410,7 +409,7 @@ static struct ptp_clock_info ptp_gianfar
 	.owner		= THIS_MODULE,
 	.name		= "gianfar clock",
 	.max_adj	= 512000,
-	.n_alarm	= N_ALARM,
+	.n_alarm	= 0,
 	.n_ext_ts	= N_EXT_TS,
 	.n_per_out	= 0,
 	.pps		= 1,
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/ibm/ibmveth.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/ibm/ibmveth.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/ibm/ibmveth.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/ibm/ibmveth.c	2013-05-11 16:57:46.000000000 -0400
@@ -1326,7 +1326,7 @@ static const struct net_device_ops ibmve
 
 static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
-	int rc, i;
+	int rc, i, mac_len;
 	struct net_device *netdev;
 	struct ibmveth_adapter *adapter;
 	unsigned char *mac_addr_p;
@@ -1336,11 +1336,19 @@ static int ibmveth_probe(struct vio_dev
 		dev->unit_address);
 
 	mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR,
-							NULL);
+							&mac_len);
 	if (!mac_addr_p) {
 		dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n");
 		return -EINVAL;
 	}
+	/* Workaround for old/broken pHyp */
+	if (mac_len == 8)
+		mac_addr_p += 2;
+	else if (mac_len != 6) {
+		dev_err(&dev->dev, "VETH_MAC_ADDR attribute wrong len %d\n",
+			mac_len);
+		return -EINVAL;
+	}
 
 	mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
 						VETH_MCAST_FILTER_SIZE, NULL);
@@ -1365,17 +1373,6 @@ static int ibmveth_probe(struct vio_dev
 
 	netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
 
-	/*
-	 * Some older boxes running PHYP non-natively have an OF that returns
-	 * a 8-byte local-mac-address field (and the first 2 bytes have to be
-	 * ignored) while newer boxes' OF return a 6-byte field. Note that
-	 * IEEE 1275 specifies that local-mac-address must be a 6-byte field.
-	 * The RPA doc specifies that the first byte must be 10b, so we'll
-	 * just look for it to solve this 8 vs. 6 byte field issue
-	 */
-	if ((*mac_addr_p & 0x3) != 0x02)
-		mac_addr_p += 2;
-
 	adapter->mac_addr = 0;
 	memcpy(&adapter->mac_addr, mac_addr_p, 6);
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/intel/e1000e/ethtool.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/intel/e1000e/ethtool.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/intel/e1000e/ethtool.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/intel/e1000e/ethtool.c	2013-05-11 16:57:46.000000000 -0400
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
+#include <linux/pm_runtime.h>
 
 #include "e1000.h"
 
@@ -2053,7 +2054,19 @@ static int e1000_get_rxnfc(struct net_de
 	}
 }
 
+static int e1000e_ethtool_begin(struct net_device *netdev)
+{
+	return pm_runtime_get_sync(netdev->dev.parent);
+}
+
+static void e1000e_ethtool_complete(struct net_device *netdev)
+{
+	pm_runtime_put_sync(netdev->dev.parent);
+}
+
 static const struct ethtool_ops e1000_ethtool_ops = {
+	.begin			= e1000e_ethtool_begin,
+	.complete		= e1000e_ethtool_complete,
 	.get_settings		= e1000_get_settings,
 	.set_settings		= e1000_set_settings,
 	.get_drvinfo		= e1000_get_drvinfo,
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c	2013-05-11 16:57:46.000000000 -0400
@@ -3952,6 +3952,7 @@ static int e1000_open(struct net_device
 	netif_start_queue(netdev);
 
 	adapter->idle_check = true;
+	hw->mac.get_link_status = true;
 	pm_runtime_put(&pdev->dev);
 
 	/* fire a link status change interrupt to start the watchdog */
@@ -4312,6 +4313,7 @@ static void e1000_phy_read_status(struct
 	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
 		int ret_val;
 
+		pm_runtime_get_sync(&adapter->pdev->dev);
 		ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
 		ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
 		ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
@@ -4322,6 +4324,7 @@ static void e1000_phy_read_status(struct
 		ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus);
 		if (ret_val)
 			e_warn("Error reading PHY register\n");
+		pm_runtime_put_sync(&adapter->pdev->dev);
 	} else {
 		/* Do not read PHY registers if link is not up
 		 * Set values to typical power-on defaults
@@ -5450,8 +5453,7 @@ release:
 	return retval;
 }
 
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
-			    bool runtime)
+static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -5475,10 +5477,6 @@ static int __e1000_shutdown(struct pci_d
 	}
 	e1000e_reset_interrupt_capability(adapter);
 
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-
 	status = er32(STATUS);
 	if (status & E1000_STATUS_LU)
 		wufc &= ~E1000_WUFC_LNKC;
@@ -5534,13 +5532,6 @@ static int __e1000_shutdown(struct pci_d
 		ew32(WUFC, 0);
 	}
 
-	*enable_wake = !!wufc;
-
-	/* make sure adapter isn't asleep if manageability is enabled */
-	if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
-	    (hw->mac.ops.check_mng_mode(hw)))
-		*enable_wake = true;
-
 	if (adapter->hw.phy.type == e1000_phy_igp_3)
 		e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
 
@@ -5549,27 +5540,7 @@ static int __e1000_shutdown(struct pci_d
 	 */
 	e1000e_release_hw_control(adapter);
 
-	pci_disable_device(pdev);
-
-	return 0;
-}
-
-static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake)
-{
-	if (sleep && wake) {
-		pci_prepare_to_sleep(pdev);
-		return;
-	}
-
-	pci_wake_from_d3(pdev, wake);
-	pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
-                                    bool wake)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
+	pci_clear_master(pdev);
 
 	/* The pci-e switch on some quad port adapters will report a
 	 * correctable error when the MAC transitions from D0 to D3.  To
@@ -5584,12 +5555,13 @@ static void e1000_complete_shutdown(stru
 		pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL,
 					   (devctl & ~PCI_EXP_DEVCTL_CERE));
 
-		e1000_power_off(pdev, sleep, wake);
+		pci_save_state(pdev);
+		pci_prepare_to_sleep(pdev);
 
 		pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl);
-	} else {
-		e1000_power_off(pdev, sleep, wake);
 	}
+
+	return 0;
 }
 
 #ifdef CONFIG_PCIEASPM
@@ -5640,9 +5612,7 @@ static int __e1000_resume(struct pci_dev
 	if (aspm_disable_flag)
 		e1000e_disable_aspm(pdev, aspm_disable_flag);
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_save_state(pdev);
+	pci_set_master(pdev);
 
 	e1000e_set_interrupt_capability(adapter);
 	if (netif_running(netdev)) {
@@ -5708,14 +5678,8 @@ static int __e1000_resume(struct pci_dev
 static int e1000_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
-	int retval;
-	bool wake;
 
-	retval = __e1000_shutdown(pdev, &wake, false);
-	if (!retval)
-		e1000_complete_shutdown(pdev, true, wake);
-
-	return retval;
+	return __e1000_shutdown(pdev, false);
 }
 
 static int e1000_resume(struct device *dev)
@@ -5738,13 +5702,10 @@ static int e1000_runtime_suspend(struct
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	if (e1000e_pm_ready(adapter)) {
-		bool wake;
-
-		__e1000_shutdown(pdev, &wake, true);
-	}
+	if (!e1000e_pm_ready(adapter))
+		return 0;
 
-	return 0;
+	return __e1000_shutdown(pdev, true);
 }
 
 static int e1000_idle(struct device *dev)
@@ -5782,12 +5743,7 @@ static int e1000_runtime_resume(struct d
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
-	bool wake = false;
-
-	__e1000_shutdown(pdev, &wake, false);
-
-	if (system_state == SYSTEM_POWER_OFF)
-		e1000_complete_shutdown(pdev, false, wake);
+	__e1000_shutdown(pdev, false);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -5908,9 +5864,9 @@ static pci_ers_result_t e1000_io_slot_re
 			"Cannot re-enable PCI device after reset.\n");
 		result = PCI_ERS_RESULT_DISCONNECT;
 	} else {
-		pci_set_master(pdev);
 		pdev->state_saved = true;
 		pci_restore_state(pdev);
+		pci_set_master(pdev);
 
 		pci_enable_wake(pdev, PCI_D3hot, 0);
 		pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -6341,7 +6297,11 @@ static int e1000_probe(struct pci_dev *p
 
 	/* initialize the wol settings based on the eeprom settings */
 	adapter->wol = adapter->eeprom_wol;
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+	/* make sure adapter isn't asleep if manageability is enabled */
+	if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) ||
+	    (hw->mac.ops.check_mng_mode(hw)))
+		device_wakeup_enable(&pdev->dev);
 
 	/* save off EEPROM version number */
 	e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c	2013-05-11 16:57:46.000000000 -0400
@@ -2407,6 +2407,16 @@ static irqreturn_t ixgbe_msix_other(int
 	 * with the write to EICR.
 	 */
 	eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+
+	/* The lower 16bits of the EICR register are for the queue interrupts
+	 * which should be masked here in order to not accidently clear them if
+	 * the bits are high when ixgbe_msix_other is called. There is a race
+	 * condition otherwise which results in possible performance loss
+	 * especially if the ixgbe_msix_other interrupt is triggering
+	 * consistently (as it would when PPS is turned on for the X540 device)
+	 */
+	eicr &= 0xFFFF0000;
+
 	IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
 
 	if (eicr & IXGBE_EICR_LSC)
@@ -7858,12 +7868,19 @@ static int __init ixgbe_init_module(void
 	ixgbe_dbg_init();
 #endif /* CONFIG_DEBUG_FS */
 
+	ret = pci_register_driver(&ixgbe_driver);
+	if (ret) {
+#ifdef CONFIG_DEBUG_FS
+		ixgbe_dbg_exit();
+#endif /* CONFIG_DEBUG_FS */
+		return ret;
+	}
+
 #ifdef CONFIG_IXGBE_DCA
 	dca_register_notify(&dca_notifier);
 #endif
 
-	ret = pci_register_driver(&ixgbe_driver);
-	return ret;
+	return 0;
 }
 
 module_init(ixgbe_init_module);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/Kconfig linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/Kconfig
--- linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -33,6 +33,7 @@ config MV643XX_ETH
 
 config MVMDIO
 	tristate "Marvell MDIO interface support"
+	select PHYLIB
 	---help---
 	  This driver supports the MDIO interface found in the network
 	  interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
@@ -45,7 +46,6 @@ config MVMDIO
 config MVNETA
 	tristate "Marvell Armada 370/XP network interface support"
 	depends on MACH_ARMADA_370_XP
-	select PHYLIB
 	select MVMDIO
 	---help---
 	  This driver supports the network interface units in the
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/mvneta.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/mvneta.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/mvneta.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/mvneta.c	2013-05-11 16:57:46.000000000 -0400
@@ -375,7 +375,6 @@ static int rxq_number = 8;
 static int txq_number = 8;
 
 static int rxq_def;
-static int txq_def;
 
 #define MVNETA_DRIVER_NAME "mvneta"
 #define MVNETA_DRIVER_VERSION "1.0"
@@ -1476,7 +1475,8 @@ error:
 static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mvneta_port *pp = netdev_priv(dev);
-	struct mvneta_tx_queue *txq = &pp->txqs[txq_def];
+	u16 txq_id = skb_get_queue_mapping(skb);
+	struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
 	struct mvneta_tx_desc *tx_desc;
 	struct netdev_queue *nq;
 	int frags = 0;
@@ -1486,7 +1486,7 @@ static int mvneta_tx(struct sk_buff *skb
 		goto out;
 
 	frags = skb_shinfo(skb)->nr_frags + 1;
-	nq    = netdev_get_tx_queue(dev, txq_def);
+	nq    = netdev_get_tx_queue(dev, txq_id);
 
 	/* Get a descriptor for the first part of the packet */
 	tx_desc = mvneta_txq_next_desc_get(txq);
@@ -2690,7 +2690,7 @@ static int mvneta_probe(struct platform_
 		return -EINVAL;
 	}
 
-	dev = alloc_etherdev_mq(sizeof(struct mvneta_port), 8);
+	dev = alloc_etherdev_mqs(sizeof(struct mvneta_port), txq_number, rxq_number);
 	if (!dev)
 		return -ENOMEM;
 
@@ -2844,4 +2844,3 @@ module_param(rxq_number, int, S_IRUGO);
 module_param(txq_number, int, S_IRUGO);
 
 module_param(rxq_def, int, S_IRUGO);
-module_param(txq_def, int, S_IRUGO);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/sky2.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/sky2.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/sky2.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/sky2.c	2013-05-11 16:57:46.000000000 -0400
@@ -1067,7 +1067,7 @@ static void sky2_ramset(struct sky2_hw *
 		sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
 		sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
 
-		tp = space - 2048/8;
+		tp = space - 8192/8;
 		sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
 		sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
 	} else {
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/sky2.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/sky2.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/marvell/sky2.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/marvell/sky2.h	2013-05-11 16:57:46.000000000 -0400
@@ -2074,7 +2074,7 @@ enum {
 	GM_IS_RX_FF_OR	= 1<<1,	/* Receive FIFO Overrun */
 	GM_IS_RX_COMPL	= 1<<0,	/* Frame Reception Complete */
 
-#define GMAC_DEF_MSK     GM_IS_TX_FF_UR
+#define GMAC_DEF_MSK     (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR)
 };
 
 /*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/mellanox/mlx4/en_netdev.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/mellanox/mlx4/en_netdev.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/mellanox/mlx4/en_netdev.c	2013-05-11 16:57:46.000000000 -0400
@@ -1434,12 +1434,11 @@ int mlx4_en_alloc_resources(struct mlx4_
 	}
 
 #ifdef CONFIG_RFS_ACCEL
-	priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->rx_ring_num);
-	if (!priv->dev->rx_cpu_rmap)
-		goto err;
-
-	INIT_LIST_HEAD(&priv->filters);
-	spin_lock_init(&priv->filters_lock);
+	if (priv->mdev->dev->caps.comp_pool) {
+		priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
+		if (!priv->dev->rx_cpu_rmap)
+			goto err;
+	}
 #endif
 
 	return 0;
@@ -1597,7 +1596,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 		err = -ENOMEM;
 		goto out;
 	}
-	priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * MAX_RX_RINGS,
+	priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * MAX_TX_RINGS,
 			      GFP_KERNEL);
 	if (!priv->tx_cq) {
 		err = -ENOMEM;
@@ -1634,6 +1633,11 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	if (err)
 		goto out;
 
+#ifdef CONFIG_RFS_ACCEL
+	INIT_LIST_HEAD(&priv->filters);
+	spin_lock_init(&priv->filters_lock);
+#endif
+
 	/* Allocate page for receive rings */
 	err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
 				MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/micrel/ks8851.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/micrel/ks8851.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/micrel/ks8851.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/micrel/ks8851.c	2013-05-11 16:57:46.000000000 -0400
@@ -547,7 +547,7 @@ static void ks8851_rx_pkts(struct ks8851
 	for (; rxfc != 0; rxfc--) {
 		rxh = ks8851_rdreg32(ks, KS_RXFHSR);
 		rxstat = rxh & 0xffff;
-		rxlen = rxh >> 16;
+		rxlen = (rxh >> 16) & 0xfff;
 
 		netif_dbg(ks, rx_status, ks->netdev,
 			  "rx: stat 0x%04x, len 0x%04x\n", rxstat, rxlen);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c	2013-05-11 16:57:46.000000000 -0400
@@ -1726,9 +1726,9 @@ pch_gbe_clean_rx(struct pch_gbe_adapter
 
 			skb->protocol = eth_type_trans(skb, netdev);
 			if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
-				skb->ip_summed = CHECKSUM_NONE;
-			else
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				skb->ip_summed = CHECKSUM_NONE;
 
 			napi_gro_receive(&adapter->napi, skb);
 			(*work_done)++;
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/realtek/r8169.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/realtek/r8169.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/realtek/r8169.c	2013-05-01 16:42:44.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/realtek/r8169.c	2013-05-11 19:18:36.000000000 -0400
@@ -3808,6 +3808,30 @@ static void rtl_init_mdio_ops(struct rtl
 	}
 }
 
+static void rtl_speed_down(struct rtl8169_private *tp)
+{
+	u32 adv;
+	int lpa;
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+	lpa = rtl_readphy(tp, MII_LPA);
+
+	if (lpa & (LPA_10HALF | LPA_10FULL))
+		adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
+	else if (lpa & (LPA_100HALF | LPA_100FULL))
+		adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+	else
+		adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+		      (tp->mii.supports_gmii ?
+		       ADVERTISED_1000baseT_Half |
+		       ADVERTISED_1000baseT_Full : 0);
+
+	rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+			  adv);
+}
+
 static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -3838,9 +3862,7 @@ static bool rtl_wol_pll_power_down(struc
 	if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
 		return false;
 
-	rtl_writephy(tp, 0x1f, 0x0000);
-	rtl_writephy(tp, MII_BMCR, 0x0000);
-
+	rtl_speed_down(tp);
 	rtl_wol_suspend_quirk(tp);
 
 	return true;
@@ -5746,6 +5768,14 @@ static netdev_tx_t rtl8169_start_xmit(st
 		goto err_stop_0;
 	}
 
+	/* 8168evl does not automatically pad to minimum length. */
+	if (unlikely(tp->mac_version == RTL_GIGA_MAC_VER_34 &&
+		     skb->len < ETH_ZLEN)) {
+		if (skb_padto(skb, ETH_ZLEN))
+			goto err_update_stats;
+		skb_put(skb, ETH_ZLEN - skb->len);
+	}
+
 	if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
 		goto err_stop_0;
 
@@ -5817,6 +5847,7 @@ err_dma_1:
 	rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
 err_dma_0:
 	dev_kfree_skb(skb);
+err_update_stats:
 	dev->stats.tx_dropped++;
 	return NETDEV_TX_OK;
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/efx.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/efx.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/efx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/efx.c	2013-05-11 16:57:46.000000000 -0400
@@ -779,6 +779,7 @@ efx_realloc_channels(struct efx_nic *efx
 						tx_queue->txd.entries);
 	}
 
+	efx_device_detach_sync(efx);
 	efx_stop_all(efx);
 	efx_stop_interrupts(efx, true);
 
@@ -832,6 +833,7 @@ out:
 
 	efx_start_interrupts(efx, true);
 	efx_start_all(efx);
+	netif_device_attach(efx->net_dev);
 	return rc;
 
 rollback:
@@ -1641,8 +1643,12 @@ static void efx_stop_all(struct efx_nic
 	/* Flush efx_mac_work(), refill_workqueue, monitor_work */
 	efx_flush_all(efx);
 
-	/* Stop the kernel transmit interface late, so the watchdog
-	 * timer isn't ticking over the flush */
+	/* Stop the kernel transmit interface.  This is only valid if
+	 * the device is stopped or detached; otherwise the watchdog
+	 * may fire immediately.
+	 */
+	WARN_ON(netif_running(efx->net_dev) &&
+		netif_device_present(efx->net_dev));
 	netif_tx_disable(efx->net_dev);
 
 	efx_stop_datapath(efx);
@@ -1963,16 +1969,18 @@ static int efx_change_mtu(struct net_dev
 	if (new_mtu > EFX_MAX_MTU)
 		return -EINVAL;
 
-	efx_stop_all(efx);
-
 	netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
 
+	efx_device_detach_sync(efx);
+	efx_stop_all(efx);
+
 	mutex_lock(&efx->mac_lock);
 	net_dev->mtu = new_mtu;
 	efx->type->reconfigure_mac(efx);
 	mutex_unlock(&efx->mac_lock);
 
 	efx_start_all(efx);
+	netif_device_attach(efx->net_dev);
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/efx.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/efx.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/efx.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/efx.h	2013-05-11 16:57:46.000000000 -0400
@@ -171,9 +171,9 @@ static inline void efx_device_detach_syn
 	 * TX scheduler is stopped when we're done and before
 	 * netif_device_present() becomes false.
 	 */
-	netif_tx_lock(dev);
+	netif_tx_lock_bh(dev);
 	netif_device_detach(dev);
-	netif_tx_unlock(dev);
+	netif_tx_unlock_bh(dev);
 }
 
 #endif /* EFX_EFX_H */
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/net_driver.h linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/net_driver.h
--- linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/net_driver.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/net_driver.h	2013-05-11 16:57:46.000000000 -0400
@@ -210,6 +210,7 @@ struct efx_tx_queue {
  *	Will be %NULL if the buffer slot is currently free.
  * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE.
  *	Will be %NULL if the buffer slot is currently free.
+ * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE.
  * @len: Buffer length, in bytes.
  * @flags: Flags for buffer and packet state.
  */
@@ -219,7 +220,8 @@ struct efx_rx_buffer {
 		struct sk_buff *skb;
 		struct page *page;
 	} u;
-	unsigned int len;
+	u16 page_offset;
+	u16 len;
 	u16 flags;
 };
 #define EFX_RX_BUF_PAGE		0x0001
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/nic.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/nic.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/nic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/nic.c	2013-05-11 16:57:46.000000000 -0400
@@ -376,7 +376,8 @@ efx_may_push_tx_desc(struct efx_tx_queue
 		return false;
 
 	tx_queue->empty_read_count = 0;
-	return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
+	return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0
+		&& tx_queue->write_count - write_count == 1;
 }
 
 /* For each entry inserted into the software descriptor ring, create a
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/ptp.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/ptp.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/ptp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/ptp.c	2013-05-11 16:57:46.000000000 -0400
@@ -1439,7 +1439,7 @@ static int efx_phc_settime(struct ptp_cl
 
 	delta = timespec_sub(*e_ts, time_now);
 
-	efx_phc_adjtime(ptp, timespec_to_ns(&delta));
+	rc = efx_phc_adjtime(ptp, timespec_to_ns(&delta));
 	if (rc != 0)
 		return rc;
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/rx.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/rx.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/sfc/rx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/sfc/rx.c	2013-05-11 16:57:46.000000000 -0400
@@ -90,11 +90,7 @@ static unsigned int rx_refill_threshold;
 static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
 					     struct efx_rx_buffer *buf)
 {
-	/* Offset is always within one page, so we don't need to consider
-	 * the page order.
-	 */
-	return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) +
-		efx->type->rx_buffer_hash_size;
+	return buf->page_offset + efx->type->rx_buffer_hash_size;
 }
 static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
 {
@@ -187,6 +183,7 @@ static int efx_init_rx_buffers_page(stru
 	struct efx_nic *efx = rx_queue->efx;
 	struct efx_rx_buffer *rx_buf;
 	struct page *page;
+	unsigned int page_offset;
 	struct efx_rx_page_state *state;
 	dma_addr_t dma_addr;
 	unsigned index, count;
@@ -211,12 +208,14 @@ static int efx_init_rx_buffers_page(stru
 		state->dma_addr = dma_addr;
 
 		dma_addr += sizeof(struct efx_rx_page_state);
+		page_offset = sizeof(struct efx_rx_page_state);
 
 	split:
 		index = rx_queue->added_count & rx_queue->ptr_mask;
 		rx_buf = efx_rx_buffer(rx_queue, index);
 		rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
 		rx_buf->u.page = page;
+		rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
 		rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
 		rx_buf->flags = EFX_RX_BUF_PAGE;
 		++rx_queue->added_count;
@@ -227,6 +226,7 @@ static int efx_init_rx_buffers_page(stru
 			/* Use the second half of the page */
 			get_page(page);
 			dma_addr += (PAGE_SIZE >> 1);
+			page_offset += (PAGE_SIZE >> 1);
 			++count;
 			goto split;
 		}
@@ -236,7 +236,8 @@ static int efx_init_rx_buffers_page(stru
 }
 
 static void efx_unmap_rx_buffer(struct efx_nic *efx,
-				struct efx_rx_buffer *rx_buf)
+				struct efx_rx_buffer *rx_buf,
+				unsigned int used_len)
 {
 	if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) {
 		struct efx_rx_page_state *state;
@@ -247,6 +248,10 @@ static void efx_unmap_rx_buffer(struct e
 				       state->dma_addr,
 				       efx_rx_buf_size(efx),
 				       DMA_FROM_DEVICE);
+		} else if (used_len) {
+			dma_sync_single_for_cpu(&efx->pci_dev->dev,
+						rx_buf->dma_addr, used_len,
+						DMA_FROM_DEVICE);
 		}
 	} else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) {
 		dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr,
@@ -269,7 +274,7 @@ static void efx_free_rx_buffer(struct ef
 static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
 			       struct efx_rx_buffer *rx_buf)
 {
-	efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
+	efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0);
 	efx_free_rx_buffer(rx_queue->efx, rx_buf);
 }
 
@@ -535,10 +540,10 @@ void efx_rx_packet(struct efx_rx_queue *
 		goto out;
 	}
 
-	/* Release card resources - assumes all RX buffers consumed in-order
-	 * per RX queue
+	/* Release and/or sync DMA mapping - assumes all RX buffers
+	 * consumed in-order per RX queue
 	 */
-	efx_unmap_rx_buffer(efx, rx_buf);
+	efx_unmap_rx_buffer(efx, rx_buf, len);
 
 	/* Prefetch nice and early so data will (hopefully) be in cache by
 	 * the time we look at it.
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/ti/cpsw.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/ti/cpsw.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/ti/cpsw.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/ti/cpsw.c	2013-05-11 16:57:46.000000000 -0400
@@ -375,7 +375,7 @@ void cpsw_tx_handler(void *token, int le
 	struct cpsw_priv	*priv = netdev_priv(ndev);
 
 	if (unlikely(netif_queue_stopped(ndev)))
-		netif_start_queue(ndev);
+		netif_wake_queue(ndev);
 	cpts_tx_timestamp(&priv->cpts, skb);
 	priv->stats.tx_packets++;
 	priv->stats.tx_bytes += len;
@@ -1111,7 +1111,7 @@ static int cpsw_probe_dt(struct cpsw_pla
 		struct platform_device *mdio;
 
 		parp = of_get_property(slave_node, "phy_id", &lenp);
-		if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
+		if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
 			pr_err("Missing slave[%d] phy_id property\n", i);
 			ret = -EINVAL;
 			goto error_ret;
diff -druNp linux-libre-3.8-gnu1/drivers/net/ethernet/ti/davinci_emac.c linux-libre-3.8.13-gnu1/drivers/net/ethernet/ti/davinci_emac.c
--- linux-libre-3.8-gnu1/drivers/net/ethernet/ti/davinci_emac.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ethernet/ti/davinci_emac.c	2013-05-11 16:57:46.000000000 -0400
@@ -1055,7 +1055,7 @@ static void emac_tx_handler(void *token,
 	atomic_dec(&priv->cur_tx);
 
 	if (unlikely(netif_queue_stopped(ndev)))
-		netif_start_queue(ndev);
+		netif_wake_queue(ndev);
 	ndev->stats.tx_packets++;
 	ndev->stats.tx_bytes += len;
 	dev_kfree_skb_any(skb);
diff -druNp linux-libre-3.8-gnu1/drivers/net/macvlan.c linux-libre-3.8.13-gnu1/drivers/net/macvlan.c
--- linux-libre-3.8-gnu1/drivers/net/macvlan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/macvlan.c	2013-05-11 16:57:46.000000000 -0400
@@ -628,6 +628,7 @@ void macvlan_common_setup(struct net_dev
 	ether_setup(dev);
 
 	dev->priv_flags	       &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
+	dev->priv_flags	       |= IFF_UNICAST_FLT;
 	dev->netdev_ops		= &macvlan_netdev_ops;
 	dev->destructor		= free_netdev;
 	dev->header_ops		= &macvlan_hard_header_ops,
diff -druNp linux-libre-3.8-gnu1/drivers/net/netconsole.c linux-libre-3.8.13-gnu1/drivers/net/netconsole.c
--- linux-libre-3.8-gnu1/drivers/net/netconsole.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/netconsole.c	2013-05-11 16:57:46.000000000 -0400
@@ -630,6 +630,7 @@ static int netconsole_netdev_event(struc
 		goto done;
 
 	spin_lock_irqsave(&target_list_lock, flags);
+restart:
 	list_for_each_entry(nt, &target_list, list) {
 		netconsole_target_get(nt);
 		if (nt->np.dev == dev) {
@@ -642,15 +643,17 @@ static int netconsole_netdev_event(struc
 			case NETDEV_UNREGISTER:
 				/*
 				 * rtnl_lock already held
+				 * we might sleep in __netpoll_cleanup()
 				 */
-				if (nt->np.dev) {
-					__netpoll_cleanup(&nt->np);
-					dev_put(nt->np.dev);
-					nt->np.dev = NULL;
-				}
+				spin_unlock_irqrestore(&target_list_lock, flags);
+				__netpoll_cleanup(&nt->np);
+				spin_lock_irqsave(&target_list_lock, flags);
+				dev_put(nt->np.dev);
+				nt->np.dev = NULL;
 				nt->enabled = 0;
 				stopped = true;
-				break;
+				netconsole_target_put(nt);
+				goto restart;
 			}
 		}
 		netconsole_target_put(nt);
diff -druNp linux-libre-3.8-gnu1/drivers/net/ppp/ppp_generic.c linux-libre-3.8.13-gnu1/drivers/net/ppp/ppp_generic.c
--- linux-libre-3.8-gnu1/drivers/net/ppp/ppp_generic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/ppp/ppp_generic.c	2013-05-11 16:57:46.000000000 -0400
@@ -1058,7 +1058,15 @@ ppp_get_stats64(struct net_device *dev,
 	return stats64;
 }
 
+static struct lock_class_key ppp_tx_busylock;
+static int ppp_dev_init(struct net_device *dev)
+{
+	dev->qdisc_tx_busylock = &ppp_tx_busylock;
+	return 0;
+}
+
 static const struct net_device_ops ppp_netdev_ops = {
+	.ndo_init	 = ppp_dev_init,
 	.ndo_start_xmit  = ppp_start_xmit,
 	.ndo_do_ioctl    = ppp_net_ioctl,
 	.ndo_get_stats64 = ppp_get_stats64,
diff -druNp linux-libre-3.8-gnu1/drivers/net/team/team.c linux-libre-3.8.13-gnu1/drivers/net/team/team.c
--- linux-libre-3.8-gnu1/drivers/net/team/team.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/team/team.c	2013-05-11 16:57:46.000000000 -0400
@@ -1139,6 +1139,8 @@ static int team_port_del(struct team *te
 	netdev_set_master(port_dev, NULL);
 	team_port_disable_netpoll(port);
 	vlan_vids_del_by_dev(port_dev, dev);
+	dev_uc_unsync(port_dev, dev);
+	dev_mc_unsync(port_dev, dev);
 	dev_close(port_dev);
 	team_port_leave(team, port);
 	team_port_set_orig_dev_addr(port);
diff -druNp linux-libre-3.8-gnu1/drivers/net/tun.c linux-libre-3.8.13-gnu1/drivers/net/tun.c
--- linux-libre-3.8-gnu1/drivers/net/tun.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/tun.c	2013-05-11 16:57:46.000000000 -0400
@@ -748,6 +748,8 @@ static netdev_tx_t tun_net_xmit(struct s
 		goto drop;
 	skb_orphan(skb);
 
+	nf_reset(skb);
+
 	/* Enqueue packet */
 	skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb);
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/usb/cdc_mbim.c linux-libre-3.8.13-gnu1/drivers/net/usb/cdc_mbim.c
--- linux-libre-3.8-gnu1/drivers/net/usb/cdc_mbim.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/usb/cdc_mbim.c	2013-05-11 16:57:46.000000000 -0400
@@ -68,18 +68,9 @@ static int cdc_mbim_bind(struct usbnet *
 	struct cdc_ncm_ctx *ctx;
 	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
 	int ret = -ENODEV;
-	u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+	u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf);
 	struct cdc_mbim_state *info = (void *)&dev->data;
 
-	/* see if interface supports MBIM alternate setting */
-	if (intf->num_altsetting == 2) {
-		if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
-			usb_set_interface(dev->udev,
-					  intf->cur_altsetting->desc.bInterfaceNumber,
-					  CDC_NCM_COMM_ALTSETTING_MBIM);
-		data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
-	}
-
 	/* Probably NCM, defer for cdc_ncm_bind */
 	if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
 		goto err;
@@ -143,7 +134,7 @@ static struct sk_buff *cdc_mbim_tx_fixup
 		goto error;
 
 	if (skb) {
-		if (skb->len <= sizeof(ETH_HLEN))
+		if (skb->len <= ETH_HLEN)
 			goto error;
 
 		/* mapping VLANs to MBIM sessions:
diff -druNp linux-libre-3.8-gnu1/drivers/net/usb/cdc_ncm.c linux-libre-3.8.13-gnu1/drivers/net/usb/cdc_ncm.c
--- linux-libre-3.8-gnu1/drivers/net/usb/cdc_ncm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/usb/cdc_ncm.c	2013-05-11 16:57:46.000000000 -0400
@@ -55,6 +55,14 @@
 
 #define	DRIVER_VERSION				"14-Mar-2012"
 
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+static bool prefer_mbim = true;
+#else
+static bool prefer_mbim;
+#endif
+module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions");
+
 static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -550,9 +558,12 @@ void cdc_ncm_unbind(struct usbnet *dev,
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
 
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+/* Select the MBIM altsetting iff it is preferred and available,
+ * returning the number of the corresponding data interface altsetting
+ */
+u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf)
 {
-	int ret;
+	struct usb_host_interface *alt;
 
 	/* The MBIM spec defines a NCM compatible default altsetting,
 	 * which we may have matched:
@@ -568,18 +579,27 @@ static int cdc_ncm_bind(struct usbnet *d
 	 *   endpoint descriptors, shall be constructed according to
 	 *   the rules given in section 6 (USB Device Model) of this
 	 *   specification."
-	 *
-	 * Do not bind to such interfaces, allowing cdc_mbim to handle
-	 * them
 	 */
-#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
-	if ((intf->num_altsetting == 2) &&
-	    !usb_set_interface(dev->udev,
-			       intf->cur_altsetting->desc.bInterfaceNumber,
-			       CDC_NCM_COMM_ALTSETTING_MBIM) &&
-	    cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+	if (prefer_mbim && intf->num_altsetting == 2) {
+		alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM);
+		if (alt && cdc_ncm_comm_intf_is_mbim(alt) &&
+		    !usb_set_interface(dev->udev,
+				       intf->cur_altsetting->desc.bInterfaceNumber,
+				       CDC_NCM_COMM_ALTSETTING_MBIM))
+			return CDC_NCM_DATA_ALTSETTING_MBIM;
+	}
+	return CDC_NCM_DATA_ALTSETTING_NCM;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting);
+
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+
+	/* MBIM backwards compatible function? */
+	cdc_ncm_select_altsetting(dev, intf);
+	if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
 		return -ENODEV;
-#endif
 
 	/* NCM data altsetting is always 1 */
 	ret = cdc_ncm_bind_common(dev, intf, 1);
diff -druNp linux-libre-3.8-gnu1/drivers/net/usb/qmi_wwan.c linux-libre-3.8.13-gnu1/drivers/net/usb/qmi_wwan.c
--- linux-libre-3.8-gnu1/drivers/net/usb/qmi_wwan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/usb/qmi_wwan.c	2013-05-11 16:57:46.000000000 -0400
@@ -139,16 +139,9 @@ static int qmi_wwan_bind(struct usbnet *
 
 	BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
 
-	/* control and data is shared? */
-	if (intf->cur_altsetting->desc.bNumEndpoints == 3) {
-		info->control = intf;
-		info->data = intf;
-		goto shared;
-	}
-
-	/* else require a single interrupt status endpoint on control intf */
-	if (intf->cur_altsetting->desc.bNumEndpoints != 1)
-		goto err;
+	/* set up initial state */
+	info->control = intf;
+	info->data = intf;
 
 	/* and a number of CDC descriptors */
 	while (len > 3) {
@@ -207,25 +200,14 @@ next_desc:
 		buf += h->bLength;
 	}
 
-	/* did we find all the required ones? */
-	if (!(found & (1 << USB_CDC_HEADER_TYPE)) ||
-	    !(found & (1 << USB_CDC_UNION_TYPE))) {
-		dev_err(&intf->dev, "CDC functional descriptors missing\n");
-		goto err;
-	}
-
-	/* verify CDC Union */
-	if (desc->bInterfaceNumber != cdc_union->bMasterInterface0) {
-		dev_err(&intf->dev, "bogus CDC Union: master=%u\n", cdc_union->bMasterInterface0);
-		goto err;
-	}
-
-	/* need to save these for unbind */
-	info->control = intf;
-	info->data = usb_ifnum_to_if(dev->udev,	cdc_union->bSlaveInterface0);
-	if (!info->data) {
-		dev_err(&intf->dev, "bogus CDC Union: slave=%u\n", cdc_union->bSlaveInterface0);
-		goto err;
+	/* Use separate control and data interfaces if we found a CDC Union */
+	if (cdc_union) {
+		info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
+		if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 || !info->data) {
+			dev_err(&intf->dev, "bogus CDC Union: master=%u, slave=%u\n",
+				cdc_union->bMasterInterface0, cdc_union->bSlaveInterface0);
+			goto err;
+		}
 	}
 
 	/* errors aren't fatal - we can live with the dynamic address */
@@ -235,11 +217,12 @@ next_desc:
 	}
 
 	/* claim data interface and set it up */
-	status = usb_driver_claim_interface(driver, info->data, dev);
-	if (status < 0)
-		goto err;
+	if (info->control != info->data) {
+		status = usb_driver_claim_interface(driver, info->data, dev);
+		if (status < 0)
+			goto err;
+	}
 
-shared:
 	status = qmi_wwan_register_subdriver(dev);
 	if (status < 0 && info->control != info->data) {
 		usb_set_intfdata(info->data, NULL);
diff -druNp linux-libre-3.8-gnu1/drivers/net/usb/smsc75xx.c linux-libre-3.8.13-gnu1/drivers/net/usb/smsc75xx.c
--- linux-libre-3.8-gnu1/drivers/net/usb/smsc75xx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/usb/smsc75xx.c	2013-05-11 16:57:46.000000000 -0400
@@ -914,8 +914,12 @@ static int smsc75xx_set_rx_max_frame_len
 static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct usbnet *dev = netdev_priv(netdev);
+	int ret;
 
-	int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
+	if (new_mtu > MAX_SINGLE_PACKET_SIZE)
+		return -EINVAL;
+
+	ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
 	if (ret < 0) {
 		netdev_warn(dev->net, "Failed to set mac rx frame length\n");
 		return ret;
@@ -1324,7 +1328,7 @@ static int smsc75xx_reset(struct usbnet
 
 	netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
 
-	ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
+	ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
 	if (ret < 0) {
 		netdev_warn(dev->net, "Failed to set max rx frame length\n");
 		return ret;
@@ -2136,8 +2140,8 @@ static int smsc75xx_rx_fixup(struct usbn
 			else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
 				dev->net->stats.rx_frame_errors++;
 		} else {
-			/* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
-			if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+			/* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */
+			if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) {
 				netif_dbg(dev, rx_err, dev->net,
 					  "size err rx_cmd_a=0x%08x\n",
 					  rx_cmd_a);
diff -druNp linux-libre-3.8-gnu1/drivers/net/usb/smsc95xx.c linux-libre-3.8.13-gnu1/drivers/net/usb/smsc95xx.c
--- linux-libre-3.8-gnu1/drivers/net/usb/smsc95xx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/usb/smsc95xx.c	2013-05-11 16:57:46.000000000 -0400
@@ -1340,6 +1340,8 @@ static int smsc95xx_enter_suspend0(struc
 	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
 	if (ret < 0)
 		netdev_warn(dev->net, "Error reading PM_CTRL\n");
+	else
+		ret = 0;
 
 	return ret;
 }
@@ -1392,6 +1394,8 @@ static int smsc95xx_enter_suspend1(struc
 	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
 	if (ret < 0)
 		netdev_warn(dev->net, "Error writing PM_CTRL\n");
+	else
+		ret = 0;
 
 	return ret;
 }
@@ -1413,6 +1417,8 @@ static int smsc95xx_enter_suspend2(struc
 	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
 	if (ret < 0)
 		netdev_warn(dev->net, "Error writing PM_CTRL\n");
+	else
+		ret = 0;
 
 	return ret;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/net/vxlan.c linux-libre-3.8.13-gnu1/drivers/net/vxlan.c
--- linux-libre-3.8-gnu1/drivers/net/vxlan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/vxlan.c	2013-05-11 16:57:46.000000000 -0400
@@ -1491,6 +1491,15 @@ static __net_init int vxlan_init_net(str
 static __net_exit void vxlan_exit_net(struct net *net)
 {
 	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+	struct vxlan_dev *vxlan;
+	struct hlist_node *pos;
+	unsigned h;
+
+	rtnl_lock();
+	for (h = 0; h < VNI_HASH_SIZE; ++h)
+		hlist_for_each_entry(vxlan, pos, &vn->vni_list[h], hlist)
+			dev_close(vxlan->dev);
+	rtnl_unlock();
 
 	if (vn->sock) {
 		sk_release_kernel(vn->sock->sk);
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c	2013-05-11 16:57:46.000000000 -0400
@@ -976,6 +976,7 @@ static bool ar9003_hw_init_cal(struct at
 					  AR_PHY_CL_TAB_1,
 					  AR_PHY_CL_TAB_2 };
 
+	/* Use chip chainmask only for calibration */
 	ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
 
 	if (rtt) {
@@ -1131,6 +1132,9 @@ skip_tx_iqcal:
 		ar9003_hw_rtt_disable(ah);
 	}
 
+	/* Revert chainmask to runtime parameters */
+	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
 	/* Initialize list pointers */
 	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
 	ah->supp_cals = IQ_MISMATCH_CAL;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h	2013-05-11 16:57:46.000000000 -0400
@@ -519,7 +519,7 @@ static const u32 ar9580_1p0_mac_core[][2
 	{0x00008258, 0x00000000},
 	{0x0000825c, 0x40000000},
 	{0x00008260, 0x00080922},
-	{0x00008264, 0x9bc00010},
+	{0x00008264, 0x9d400010},
 	{0x00008268, 0xffffffff},
 	{0x0000826c, 0x0000ffff},
 	{0x00008270, 0x00000000},
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/common.h linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/common.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/common.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/common.h	2013-05-11 16:57:46.000000000 -0400
@@ -27,7 +27,7 @@
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 #define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 
-#define ATH_RSSI_DUMMY_MARKER   0x127
+#define ATH_RSSI_DUMMY_MARKER   127
 #define ATH_RSSI_LPF_LEN 		10
 #define RSSI_LPF_THRESHOLD		-20
 #define ATH_RSSI_EP_MULTIPLIER     (1<<7)
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c	2013-05-11 16:57:46.000000000 -0400
@@ -796,7 +796,7 @@ static int ath9k_init_firmware_version(s
 	 * required version.
 	 */
 	if (priv->fw_version_major != MAJOR_VERSION_REQ ||
-	    priv->fw_version_minor != MINOR_VERSION_REQ) {
+	    priv->fw_version_minor < MINOR_VERSION_REQ) {
 		dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
 			MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
 		return -EINVAL;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2013-05-11 16:57:46.000000000 -0400
@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9
 
 	last_rssi = priv->rx.last_rssi;
 
-	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-		rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
-						     ATH_RSSI_EP_MULTIPLIER);
+	if (ieee80211_is_beacon(hdr->frame_control) &&
+	    !is_zero_ether_addr(common->curbssid) &&
+	    ether_addr_equal(hdr->addr3, common->curbssid)) {
+		s8 rssi = rxbuf->rxstatus.rs_rssi;
 
-	if (rxbuf->rxstatus.rs_rssi < 0)
-		rxbuf->rxstatus.rs_rssi = 0;
+		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
 
-	if (ieee80211_is_beacon(fc))
-		priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
+		if (rssi < 0)
+			rssi = 0;
+
+		priv->ah->stats.avgbrssi = rssi;
+	}
 
 	rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
 	rx_status->band = hw->conf.channel->band;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/htc.h linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/htc.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/htc.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/htc.h	2013-05-11 16:57:46.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/firmware.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/hw.c linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/hw.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/hw.c	2013-05-11 16:57:46.000000000 -0400
@@ -1480,7 +1480,9 @@ static bool ath9k_hw_chip_reset(struct a
 			reset_type = ATH9K_RESET_POWER_ON;
 		else
 			reset_type = ATH9K_RESET_COLD;
-	}
+	} else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) ||
+		   (REG_READ(ah, AR_CR) & AR_CR_RXE))
+		reset_type = ATH9K_RESET_COLD;
 
 	if (!ath9k_hw_set_reset_reg(ah, reset_type))
 		return false;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/link.c linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/link.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/ath/ath9k/link.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/ath/ath9k/link.c	2013-05-11 16:57:46.000000000 -0400
@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct wo
 	int i;
 	bool needreset = false;
 
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i)) {
-			txq = &sc->tx.txq[i];
-			ath_txq_lock(sc, txq);
-			if (txq->axq_depth) {
-				if (txq->axq_tx_inprogress) {
-					needreset = true;
-					ath_txq_unlock(sc, txq);
-					break;
-				} else {
-					txq->axq_tx_inprogress = true;
-				}
+	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+		txq = sc->tx.txq_map[i];
+
+		ath_txq_lock(sc, txq);
+		if (txq->axq_depth) {
+			if (txq->axq_tx_inprogress) {
+				needreset = true;
+				ath_txq_unlock(sc, txq);
+				break;
+			} else {
+				txq->axq_tx_inprogress = true;
 			}
-			ath_txq_unlock_complete(sc, txq);
 		}
+		ath_txq_unlock_complete(sc, txq);
+	}
 
 	if (needreset) {
 		ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
@@ -170,7 +170,8 @@ void ath_rx_poll(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *)data;
 
-	ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+	if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
+		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 }
 
 /*
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/b43/dma.c linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/dma.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/b43/dma.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/dma.c	2013-05-11 16:57:46.000000000 -0400
@@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_
 	const struct b43_dma_ops *ops;
 	struct b43_dmaring *ring;
 	struct b43_dmadesc_meta *meta;
+	static const struct b43_txstatus fake; /* filled with 0 */
+	const struct b43_txstatus *txstat;
 	int slot, firstused;
 	bool frame_succeed;
+	int skip;
+	static u8 err_out1, err_out2;
 
 	ring = parse_cookie(dev, status->cookie, &slot);
 	if (unlikely(!ring))
@@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_
 	firstused = ring->current_slot - ring->used_slots + 1;
 	if (firstused < 0)
 		firstused = ring->nr_slots + firstused;
+
+	skip = 0;
 	if (unlikely(slot != firstused)) {
 		/* This possibly is a firmware bug and will result in
-		 * malfunction, memory leaks and/or stall of DMA functionality. */
-		b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
-		       "Expected %d, but got %d\n",
-		       ring->index, firstused, slot);
-		return;
+		 * malfunction, memory leaks and/or stall of DMA functionality.
+		 */
+		if (slot == next_slot(ring, next_slot(ring, firstused))) {
+			/* If a single header/data pair was missed, skip over
+			 * the first two slots in an attempt to recover.
+			 */
+			slot = firstused;
+			skip = 2;
+			if (!err_out1) {
+				/* Report the error once. */
+				b43dbg(dev->wl,
+				       "Skip on DMA ring %d slot %d.\n",
+				       ring->index, slot);
+				err_out1 = 1;
+			}
+		} else {
+			/* More than a single header/data pair were missed.
+			 * Report this error once.
+			 */
+			if (!err_out2)
+				b43dbg(dev->wl,
+				       "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+				       ring->index, firstused, slot);
+			err_out2 = 1;
+			return;
+		}
 	}
 
 	ops = ring->ops;
@@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_
 			       slot, firstused, ring->index);
 			break;
 		}
+
 		if (meta->skb) {
 			struct b43_private_tx_info *priv_info =
-				b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+			     b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
 
-			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
 			kfree(priv_info->bouncebuffer);
 			priv_info->bouncebuffer = NULL;
 		} else {
@@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_
 			struct ieee80211_tx_info *info;
 
 			if (unlikely(!meta->skb)) {
-				/* This is a scatter-gather fragment of a frame, so
-				 * the skb pointer must not be NULL. */
+				/* This is a scatter-gather fragment of a frame,
+				 * so the skb pointer must not be NULL.
+				 */
 				b43dbg(dev->wl, "TX status unexpected NULL skb "
 				       "at slot %d (first=%d) on ring %d\n",
 				       slot, firstused, ring->index);
@@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_
 
 			/*
 			 * Call back to inform the ieee80211 subsystem about
-			 * the status of the transmission.
+			 * the status of the transmission. When skipping over
+			 * a missed TX status report, use a status structure
+			 * filled with zeros to indicate that the frame was not
+			 * sent (frame_count 0) and not acknowledged
 			 */
-			frame_succeed = b43_fill_txstatus_report(dev, info, status);
+			if (unlikely(skip))
+				txstat = &fake;
+			else
+				txstat = status;
+
+			frame_succeed = b43_fill_txstatus_report(dev, info,
+								 txstat);
 #ifdef CONFIG_B43_DEBUG
 			if (frame_succeed)
 				ring->nr_succeed_tx_packets++;
@@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_
 		/* Everything unmapped and free'd. So it's not used anymore. */
 		ring->used_slots--;
 
-		if (meta->is_last_fragment) {
+		if (meta->is_last_fragment && !skip) {
 			/* This is the last scatter-gather
 			 * fragment of the frame. We are done. */
 			break;
 		}
 		slot = next_slot(ring, slot);
+		if (skip > 0)
+			--skip;
 	}
 	if (ring->stopped) {
 		B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/b43/dma.h linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/dma.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/b43/dma.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/dma.h	2013-05-11 16:57:46.000000000 -0400
@@ -169,7 +169,7 @@ struct b43_dmadesc_generic {
 
 /* DMA engine tuning knobs */
 #define B43_TXRING_SLOTS		256
-#define B43_RXRING_SLOTS		64
+#define B43_RXRING_SLOTS		256
 #define B43_DMA0_RX_FW598_BUFSIZE	(B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
 #define B43_DMA0_RX_FW351_BUFSIZE	(B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/b43/main.c linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/main.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/b43/main.c	2013-05-01 16:43:34.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/main.c	2013-05-11 19:19:26.000000000 -0400
@@ -4210,7 +4210,6 @@ redo:
 	mutex_unlock(&wl->mutex);
 	cancel_delayed_work_sync(&dev->periodic_work);
 	cancel_work_sync(&wl->tx_work);
-	cancel_work_sync(&wl->firmware_load);
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
 	if (!dev || b43_status(dev) < B43_STAT_STARTED) {
@@ -5430,6 +5429,7 @@ static void b43_bcma_remove(struct bcma_
 	/* We must cancel any work here before unregistering from ieee80211,
 	 * as the ieee80211 unreg will destroy the workqueue. */
 	cancel_work_sync(&wldev->restart_work);
+	cancel_work_sync(&wl->firmware_load);
 
 	B43_WARN_ON(!wl);
 	if (!wldev->fw.ucode.data)
@@ -5506,6 +5506,7 @@ static void b43_ssb_remove(struct ssb_de
 	/* We must cancel any work here before unregistering from ieee80211,
 	 * as the ieee80211 unreg will destroy the workqueue. */
 	cancel_work_sync(&wldev->restart_work);
+	cancel_work_sync(&wl->firmware_load);
 
 	B43_WARN_ON(!wl);
 	if (!wldev->fw.ucode.data)
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/b43/phy_n.c linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/phy_n.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/b43/phy_n.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/b43/phy_n.c	2013-05-11 16:57:46.000000000 -0400
@@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struc
 	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
 
 	u8 vcm_final = 0;
-	s8 offset[4];
+	s32 offset[4];
 	s32 results[8][4] = { };
 	s32 results_min[4] = { };
 	s32 poll_results[4] = { };
@@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struc
 		}
 		for (i = 0; i < 4; i += 2) {
 			s32 curr;
-			s32 mind = 40;
+			s32 mind = 0x100000;
 			s32 minpoll = 249;
 			u8 minvcm = 0;
 			if (2 * core != i)
@@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struc
 	u8 regs_save_radio[2];
 	u16 regs_save_phy[2];
 
-	s8 offset[4];
+	s32 offset[4];
 	u8 core;
 	u8 rail;
 
@@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struc
 	}
 
 	for (i = 0; i < 4; i++) {
-		s32 mind = 40;
+		s32 mind = 0x100000;
 		u8 minvcm = 0;
 		s32 minpoll = 249;
 		s32 curr;
@@ -5165,7 +5165,8 @@ static void b43_nphy_pmu_spur_avoid(stru
 #endif
 #ifdef CONFIG_B43_SSB
 	case B43_BUS_SSB:
-		/* FIXME */
+		ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
+					    avoid);
 		break;
 #endif
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c linux-libre-3.8.13-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c	2013-05-11 16:57:46.000000000 -0400
@@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(s
 	gain0_15 = ((biq1 & 0xf) << 12) |
 		   ((tia & 0xf) << 8) |
 		   ((lna2 & 0x3) << 6) |
-		   ((lna2 & 0x3) << 4) |
-		   ((lna1 & 0x3) << 2) |
-		   ((lna1 & 0x3) << 0);
+		   ((lna2 &
+		     0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
 
 	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
 	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
@@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(s
 	}
 
 	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-	mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
 
 }
 
@@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_po
 	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
 }
 
-static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
-				      u16 tia_gain, u16 lna2_gain)
-{
-	u32 i_thresh_l, q_thresh_l;
-	u32 i_thresh_h, q_thresh_h;
-	struct lcnphy_iq_est iq_est_h, iq_est_l;
-
-	wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
-					       lna2_gain, 0);
-
-	wlc_lcnphy_rx_gain_override_enable(pi, true);
-	wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
-	udelay(500);
-	write_radio_reg(pi, RADIO_2064_REG112, 0);
-	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
-		return false;
-
-	wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
-	udelay(500);
-	write_radio_reg(pi, RADIO_2064_REG112, 0);
-	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
-		return false;
-
-	i_thresh_l = (iq_est_l.i_pwr << 1);
-	i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
-
-	q_thresh_l = (iq_est_l.q_pwr << 1);
-	q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
-	if ((iq_est_h.i_pwr > i_thresh_l) &&
-	    (iq_est_h.i_pwr < i_thresh_h) &&
-	    (iq_est_h.q_pwr > q_thresh_l) &&
-	    (iq_est_h.q_pwr < q_thresh_h))
-		return true;
-
-	return false;
-}
-
 static bool
 wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 		     const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *p
 	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
 	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
 	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-	int tia_gain, lna2_gain, biq1_gain;
-	bool set_gain;
+	int tia_gain;
+	u32 received_power, rx_pwr_threshold;
 	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
 	u16 values_to_save[11];
 	s16 *ptr;
@@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *p
 		goto cal_done;
 	}
 
-	WARN_ON(module != 1);
-	tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	for (i = 0; i < 11; i++)
-		values_to_save[i] =
-			read_radio_reg(pi, rxiq_cal_rf_reg[i]);
-	Core1TxControl_old = read_phy_reg(pi, 0x631);
-
-	or_phy_reg(pi, 0x631, 0x0015);
+	if (module == 1) {
 
-	RFOverride0_old = read_phy_reg(pi, 0x44c);
-	RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
-	rfoverride2_old = read_phy_reg(pi, 0x4b0);
-	rfoverride2val_old = read_phy_reg(pi, 0x4b1);
-	rfoverride3_old = read_phy_reg(pi, 0x4f9);
-	rfoverride3val_old = read_phy_reg(pi, 0x4fa);
-	rfoverride4_old = read_phy_reg(pi, 0x938);
-	rfoverride4val_old = read_phy_reg(pi, 0x939);
-	afectrlovr_old = read_phy_reg(pi, 0x43b);
-	afectrlovrval_old = read_phy_reg(pi, 0x43c);
-	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-	old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
 
-	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-	if (tx_gain_override_old) {
-		wlc_lcnphy_get_tx_gain(pi, &old_gains);
-		tx_gain_index_old = pi_lcn->lcnphy_current_index;
-	}
+		for (i = 0; i < 11; i++)
+			values_to_save[i] =
+				read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+		Core1TxControl_old = read_phy_reg(pi, 0x631);
 
-	wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+		or_phy_reg(pi, 0x631, 0x0015);
 
-	mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		RFOverride0_old = read_phy_reg(pi, 0x44c);
+		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+		rfoverride2_old = read_phy_reg(pi, 0x4b0);
+		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+		rfoverride3_old = read_phy_reg(pi, 0x4f9);
+		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+		rfoverride4_old = read_phy_reg(pi, 0x938);
+		rfoverride4val_old = read_phy_reg(pi, 0x939);
+		afectrlovr_old = read_phy_reg(pi, 0x43b);
+		afectrlovrval_old = read_phy_reg(pi, 0x43c);
+		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
 
-	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+		if (tx_gain_override_old) {
+			wlc_lcnphy_get_tx_gain(pi, &old_gains);
+			tx_gain_index_old = pi_lcn->lcnphy_current_index;
+		}
 
-	write_radio_reg(pi, RADIO_2064_REG116, 0x06);
-	write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
-	write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
-	write_radio_reg(pi, RADIO_2064_REG098, 0x03);
-	write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-	mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
-	write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
-	write_radio_reg(pi, RADIO_2064_REG114, 0x01);
-	write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
-	write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
 
-	mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
-	mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
-	mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
-	mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
-	mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
-	mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
-	mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
 
-	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
 
-	write_phy_reg(pi, 0x6da, 0xffff);
-	or_phy_reg(pi, 0x6db, 0x3);
+		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
 
-	wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-	set_gain = false;
+		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
 
-	lna2_gain = 3;
-	while ((lna2_gain >= 0) && !set_gain) {
-		tia_gain = 4;
+		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
 
-		while ((tia_gain >= 0) && !set_gain) {
-			biq1_gain = 6;
+		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+		write_phy_reg(pi, 0x6da, 0xffff);
+		or_phy_reg(pi, 0x6db, 0x3);
+		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+		wlc_lcnphy_rx_gain_override_enable(pi, true);
 
-			while ((biq1_gain >= 0) && !set_gain) {
-				set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
-								     (u16)
-								     biq1_gain,
-								     (u16)
-								     tia_gain,
-								     (u16)
-								     lna2_gain);
-				biq1_gain -= 1;
-			}
+		tia_gain = 8;
+		rx_pwr_threshold = 950;
+		while (tia_gain > 0) {
 			tia_gain -= 1;
-		}
-		lna2_gain -= 1;
-	}
+			wlc_lcnphy_set_rx_gain_by_distribution(pi,
+							       0, 0, 2, 2,
+							       (u16)
+							       tia_gain, 1, 0);
+			udelay(500);
 
-	if (set_gain)
-		result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
-	else
-		result = false;
+			received_power =
+				wlc_lcnphy_measure_digital_power(pi, 2000);
+			if (received_power < rx_pwr_threshold)
+				break;
+		}
+		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
 
-	wlc_lcnphy_stop_tx_tone(pi);
+		wlc_lcnphy_stop_tx_tone(pi);
 
-	write_phy_reg(pi, 0x631, Core1TxControl_old);
+		write_phy_reg(pi, 0x631, Core1TxControl_old);
 
-	write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
-	write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
-	write_phy_reg(pi, 0x4b0, rfoverride2_old);
-	write_phy_reg(pi, 0x4b1, rfoverride2val_old);
-	write_phy_reg(pi, 0x4f9, rfoverride3_old);
-	write_phy_reg(pi, 0x4fa, rfoverride3val_old);
-	write_phy_reg(pi, 0x938, rfoverride4_old);
-	write_phy_reg(pi, 0x939, rfoverride4val_old);
-	write_phy_reg(pi, 0x43b, afectrlovr_old);
-	write_phy_reg(pi, 0x43c, afectrlovrval_old);
-	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-	write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x4b0, rfoverride2_old);
+		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+		write_phy_reg(pi, 0x4f9, rfoverride3_old);
+		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+		write_phy_reg(pi, 0x938, rfoverride4_old);
+		write_phy_reg(pi, 0x939, rfoverride4val_old);
+		write_phy_reg(pi, 0x43b, afectrlovr_old);
+		write_phy_reg(pi, 0x43c, afectrlovrval_old);
+		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
 
-	wlc_lcnphy_clear_trsw_override(pi);
+		wlc_lcnphy_clear_trsw_override(pi);
 
-	mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
 
-	for (i = 0; i < 11; i++)
-		write_radio_reg(pi, rxiq_cal_rf_reg[i],
-				values_to_save[i]);
+		for (i = 0; i < 11; i++)
+			write_radio_reg(pi, rxiq_cal_rf_reg[i],
+					values_to_save[i]);
 
-	if (tx_gain_override_old)
-		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
-	else
-		wlc_lcnphy_disable_tx_gain_override(pi);
+		if (tx_gain_override_old)
+			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+		else
+			wlc_lcnphy_disable_tx_gain_override(pi);
 
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-	wlc_lcnphy_rx_gain_override_enable(pi, false);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+		wlc_lcnphy_rx_gain_override_enable(pi, false);
+	}
 
 cal_done:
 	kfree(ptr);
@@ -1829,17 +1781,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(
 		write_radio_reg(pi, RADIO_2064_REG038, 3);
 		write_radio_reg(pi, RADIO_2064_REG091, 7);
 	}
-
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
-			0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
-
-		write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
-		write_radio_reg(pi, RADIO_2064_REG091, 0x3);
-		write_radio_reg(pi, RADIO_2064_REG038, 0x3);
-
-		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
-	}
 }
 
 static int
@@ -2034,16 +1975,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy
 		} else {
 			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
 			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
-			mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
-			mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
-			mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
-			mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
-			mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
 		}
 	} else {
 		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2130,14 +2061,12 @@ static void wlc_lcnphy_pwrctrl_rssiparam
 		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
 
 	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-	mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
 }
 
 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 {
 	struct phytbl_info tab;
 	u32 rfseq, ind;
-	u8 tssi_sel;
 
 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
 	tab.tbl_width = 32;
@@ -2159,13 +2088,7 @@ static void wlc_lcnphy_tssi_setup(struct
 
 	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
 
-	if (pi->sh->boardflags & BFL_FEM) {
-		tssi_sel = 0x1;
-		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-	} else {
-		tssi_sel = 0xe;
-		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
-	}
+	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
 	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
 
 	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
@@ -2201,10 +2124,9 @@ static void wlc_lcnphy_tssi_setup(struct
 	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
 
 	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
+		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
 		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
 	} else {
-		mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
 		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
 		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
 	}
@@ -2251,10 +2173,6 @@ static void wlc_lcnphy_tssi_setup(struct
 
 	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
 
-	mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
-	mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-	mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-
 	wlc_lcnphy_pwrctrl_rssiparams(pi);
 }
 
@@ -2873,8 +2791,6 @@ static void wlc_lcnphy_idle_tssi_est(str
 		read_radio_reg(pi, RADIO_2064_REG007) & 1;
 	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
 	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
-	u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
-
 	idleTssi = read_phy_reg(pi, 0x4ab);
 	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
 			 MCTL_EN_MAC));
@@ -2892,12 +2808,6 @@ static void wlc_lcnphy_idle_tssi_est(str
 	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
 	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
 	wlc_lcnphy_tssi_setup(pi);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
-	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
-
-	wlc_lcnphy_set_bbmult(pi, 0x0);
-
 	wlc_phy_do_dummy_tx(pi, true, OFF);
 	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
 		    >> 0);
@@ -2919,7 +2829,6 @@ static void wlc_lcnphy_idle_tssi_est(str
 
 	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
 
-	wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
 	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
 	wlc_lcnphy_set_tx_gain(pi, &old_gains);
 	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
@@ -3133,11 +3042,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(
 			wlc_lcnphy_write_table(pi, &tab);
 			tab.tbl_offset++;
 		}
-		mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
-		mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
-		mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
-		mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
-		mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
 
 		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
 
@@ -3939,6 +3843,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal
 	target_gains.pad_gain = 21;
 	target_gains.dac_gain = 0;
 	wlc_lcnphy_set_tx_gain(pi, &target_gains);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 
 	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
 
@@ -3949,7 +3854,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal
 					lcnphy_recal ? LCNPHY_CAL_RECAL :
 					LCNPHY_CAL_FULL), false);
 	} else {
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
 	}
 
@@ -4374,22 +4278,17 @@ wlc_lcnphy_load_tx_gain_table(struct brc
 	if (CHSPEC_IS5G(pi->radio_chanspec))
 		pa_gain = 0x70;
 	else
-		pa_gain = 0x60;
+		pa_gain = 0x70;
 
 	if (pi->sh->boardflags & BFL_FEM)
 		pa_gain = 0x10;
-
 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
 	tab.tbl_width = 32;
 	tab.tbl_len = 1;
 	tab.tbl_ptr = &val;
 
 	for (j = 0; j < 128; j++) {
-		if (pi->sh->boardflags & BFL_FEM)
-			gm_gain = gain_table[j].gm;
-		else
-			gm_gain = 15;
-
+		gm_gain = gain_table[j].gm;
 		val = (((u32) pa_gain << 24) |
 		       (gain_table[j].pad << 16) |
 		       (gain_table[j].pga << 8) | gm_gain);
@@ -4600,10 +4499,7 @@ static void wlc_radio_2064_init(struct b
 
 	write_phy_reg(pi, 0x4ea, 0x4688);
 
-	if (pi->sh->boardflags & BFL_FEM)
-		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-	else
-		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
+	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
 
 	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
 
@@ -4614,13 +4510,6 @@ static void wlc_radio_2064_init(struct b
 	wlc_lcnphy_rcal(pi);
 
 	wlc_lcnphy_rc_cal(pi);
-
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
-		write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-		write_radio_reg(pi, RADIO_2064_REG039, 0xe);
-	}
-
 }
 
 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4650,20 +4539,22 @@ static void wlc_lcnphy_tbl_init(struct b
 		wlc_lcnphy_write_table(pi, &tab);
 	}
 
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-		tab.tbl_width = 16;
-		tab.tbl_ptr = &val;
-		tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &val;
+	tab.tbl_len = 1;
 
-		val = 150;
-		tab.tbl_offset = 0;
-		wlc_lcnphy_write_table(pi, &tab);
+	val = 114;
+	tab.tbl_offset = 0;
+	wlc_lcnphy_write_table(pi, &tab);
 
-		val = 220;
-		tab.tbl_offset = 1;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
+	val = 130;
+	tab.tbl_offset = 1;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 6;
+	tab.tbl_offset = 8;
+	wlc_lcnphy_write_table(pi, &tab);
 
 	if (CHSPEC_IS2G(pi->radio_chanspec)) {
 		if (pi->sh->boardflags & BFL_FEM)
@@ -5055,7 +4946,6 @@ void wlc_phy_chanspec_set_lcnphy(struct
 		wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
 
 	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-	wlc_lcnphy_tssi_setup(pi);
 }
 
 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5094,7 +4984,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_
 	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
 		return false;
 
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+	if ((pi->sh->boardflags & BFL_FEM) &&
+	    (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
 		if (pi_lcn->lcnphy_tempsense_option == 3) {
 			pi->hwpwrctrl = true;
 			pi->hwpwrctrl_capable = true;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c linux-libre-3.8.13-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c	2013-05-11 16:57:46.000000000 -0400
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_43
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/debugfs.c linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/debugfs.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/debugfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/debugfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -2237,15 +2237,15 @@ static ssize_t iwl_dbgfs_log_event_read(
 					 size_t count, loff_t *ppos)
 {
 	struct iwl_priv *priv = file->private_data;
-	char *buf;
-	int pos = 0;
-	ssize_t ret = -ENOMEM;
+	char *buf = NULL;
+	ssize_t ret;
 
-	ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
-	if (buf) {
-		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-		kfree(buf);
-	}
+	ret = iwl_dump_nic_event_log(priv, true, &buf, true);
+	if (ret < 0)
+		goto err;
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+err:
+	kfree(buf);
 	return ret;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/lib.c linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/lib.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/lib.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/lib.c	2013-05-11 16:57:46.000000000 -0400
@@ -1262,6 +1262,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *pr
 	}
 
 	/*
+	 * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag
+	 * in iwl_down but cancel the workers only later.
+	 */
+	if (!priv->ucode_loaded) {
+		IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
+		return -EIO;
+	}
+
+	/*
 	 * Synchronous commands from this op-mode must hold
 	 * the mutex, this ensures we don't try to send two
 	 * (or more) synchronous commands at a time.
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/sta.c linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/sta.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/sta.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/sta.c	2013-05-11 16:57:46.000000000 -0400
@@ -707,6 +707,7 @@ void iwl_clear_ucode_stations(struct iwl
 void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
 	struct iwl_addsta_cmd sta_cmd;
+	static const struct iwl_link_quality_cmd zero_lq = {};
 	struct iwl_link_quality_cmd lq;
 	int i;
 	bool found = false;
@@ -745,7 +746,9 @@ void iwl_restore_stations(struct iwl_pri
 				else
 					memcpy(&lq, priv->stations[i].lq,
 					       sizeof(struct iwl_link_quality_cmd));
-				send_lq = true;
+
+				if (!memcmp(&lq, &zero_lq, sizeof(lq)))
+					send_lq = true;
 			}
 			spin_unlock_bh(&priv->sta_lock);
 			ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/ucode.c linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/ucode.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/dvm/ucode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/dvm/ucode.c	2013-05-11 16:57:46.000000000 -0400
@@ -450,6 +450,8 @@ int iwl_load_ucode_wait_alive(struct iwl
 		return -EIO;
 	}
 
+	priv->ucode_loaded = true;
+
 	/*
 	 * This step takes a long time (60-80ms!!) and
 	 * WoWLAN image should be loaded quickly, so
@@ -474,8 +476,6 @@ int iwl_load_ucode_wait_alive(struct iwl
 		return ret;
 	}
 
-	priv->ucode_loaded = true;
-
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/iwl-devtrace.h linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/iwl-devtrace.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/iwl-devtrace.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/iwl-devtrace.h	2013-05-11 16:57:46.000000000 -0400
@@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data,
 TRACE_EVENT(iwlwifi_dev_hcmd,
 	TP_PROTO(const struct device *dev,
 		 struct iwl_host_cmd *cmd, u16 total_size,
-		 const void *hdr, size_t hdr_len),
-	TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
+		 struct iwl_cmd_header *hdr),
+	TP_ARGS(dev, cmd, total_size, hdr),
 	TP_STRUCT__entry(
 		DEV_ENTRY
 		__dynamic_array(u8, hcmd, total_size)
 		__field(u32, flags)
 	),
 	TP_fast_assign(
-		int i, offset = hdr_len;
+		int i, offset = sizeof(*hdr);
 
 		DEV_ASSIGN;
 		__entry->flags = cmd->flags;
-		memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
+		memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
 
 		for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
 			if (!cmd->len[i])
 				continue;
-			if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
-				continue;
 			memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
 			       cmd->data[i], cmd->len[i]);
 			offset += cmd->len[i];
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/pcie/internal.h linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/pcie/internal.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/pcie/internal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/pcie/internal.h	2013-05-11 16:57:46.000000000 -0400
@@ -182,6 +182,15 @@ struct iwl_queue {
 #define TFD_TX_CMD_SLOTS 256
 #define TFD_CMD_SLOTS 32
 
+/*
+ * The FH will write back to the first TB only, so we need
+ * to copy some data into the buffer regardless of whether
+ * it should be mapped or not. This indicates how much to
+ * copy, even for HCMDs it must be big enough to fit the
+ * DRAM scratch from the TX cmd, at least 16 bytes.
+ */
+#define IWL_HCMD_MIN_COPY_SIZE	16
+
 struct iwl_pcie_txq_entry {
 	struct iwl_device_cmd *cmd;
 	struct iwl_device_cmd *copy_cmd;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/pcie/tx.c linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/pcie/tx.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/iwlwifi/pcie/tx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/iwlwifi/pcie/tx.c	2013-05-11 16:57:46.000000000 -0400
@@ -1131,10 +1131,12 @@ static int iwl_pcie_enqueue_hcmd(struct
 	void *dup_buf = NULL;
 	dma_addr_t phys_addr;
 	int idx;
-	u16 copy_size, cmd_size;
+	u16 copy_size, cmd_size, dma_size;
 	bool had_nocopy = false;
 	int i;
 	u32 cmd_pos;
+	const u8 *cmddata[IWL_MAX_CMD_TFDS];
+	u16 cmdlen[IWL_MAX_CMD_TFDS];
 
 	copy_size = sizeof(out_cmd->hdr);
 	cmd_size = sizeof(out_cmd->hdr);
@@ -1143,8 +1145,23 @@ static int iwl_pcie_enqueue_hcmd(struct
 	BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
 
 	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+		cmddata[i] = cmd->data[i];
+		cmdlen[i] = cmd->len[i];
+
 		if (!cmd->len[i])
 			continue;
+
+		/* need at least IWL_HCMD_MIN_COPY_SIZE copied */
+		if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
+			int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
+
+			if (copy > cmdlen[i])
+				copy = cmdlen[i];
+			cmdlen[i] -= copy;
+			cmddata[i] += copy;
+			copy_size += copy;
+		}
+
 		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
 			had_nocopy = true;
 			if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
@@ -1164,7 +1181,7 @@ static int iwl_pcie_enqueue_hcmd(struct
 				goto free_dup_buf;
 			}
 
-			dup_buf = kmemdup(cmd->data[i], cmd->len[i],
+			dup_buf = kmemdup(cmddata[i], cmdlen[i],
 					  GFP_ATOMIC);
 			if (!dup_buf)
 				return -ENOMEM;
@@ -1174,7 +1191,7 @@ static int iwl_pcie_enqueue_hcmd(struct
 				idx = -EINVAL;
 				goto free_dup_buf;
 			}
-			copy_size += cmd->len[i];
+			copy_size += cmdlen[i];
 		}
 		cmd_size += cmd->len[i];
 	}
@@ -1221,14 +1238,31 @@ static int iwl_pcie_enqueue_hcmd(struct
 
 	/* and copy the data that needs to be copied */
 	cmd_pos = offsetof(struct iwl_device_cmd, payload);
+	copy_size = sizeof(out_cmd->hdr);
 	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+		int copy = 0;
+
 		if (!cmd->len[i])
 			continue;
-		if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
-					 IWL_HCMD_DFL_DUP))
-			break;
-		memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
-		cmd_pos += cmd->len[i];
+
+		/* need at least IWL_HCMD_MIN_COPY_SIZE copied */
+		if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
+			copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
+
+			if (copy > cmd->len[i])
+				copy = cmd->len[i];
+		}
+
+		/* copy everything if not nocopy/dup */
+		if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+					   IWL_HCMD_DFL_DUP)))
+			copy = cmd->len[i];
+
+		if (copy) {
+			memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
+			cmd_pos += copy;
+			copy_size += copy;
+		}
 	}
 
 	WARN_ON_ONCE(txq->entries[idx].copy_cmd);
@@ -1254,7 +1288,14 @@ static int iwl_pcie_enqueue_hcmd(struct
 		     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
 		     cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
 
-	phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
+	/*
+	 * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must
+	 * still map at least that many bytes for the hardware to write back to.
+	 * We have enough space, so that's not a problem.
+	 */
+	dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE);
+
+	phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size,
 				   DMA_BIDIRECTIONAL);
 	if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
 		idx = -ENOMEM;
@@ -1262,14 +1303,15 @@ static int iwl_pcie_enqueue_hcmd(struct
 	}
 
 	dma_unmap_addr_set(out_meta, mapping, phys_addr);
-	dma_unmap_len_set(out_meta, len, copy_size);
+	dma_unmap_len_set(out_meta, len, dma_size);
 
 	iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
 
+	/* map the remaining (adjusted) nocopy/dup fragments */
 	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-		const void *data = cmd->data[i];
+		const void *data = cmddata[i];
 
-		if (!cmd->len[i])
+		if (!cmdlen[i])
 			continue;
 		if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
 					   IWL_HCMD_DFL_DUP)))
@@ -1277,7 +1319,7 @@ static int iwl_pcie_enqueue_hcmd(struct
 		if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
 			data = dup_buf;
 		phys_addr = dma_map_single(trans->dev, (void *)data,
-					   cmd->len[i], DMA_BIDIRECTIONAL);
+					   cmdlen[i], DMA_BIDIRECTIONAL);
 		if (dma_mapping_error(trans->dev, phys_addr)) {
 			iwl_pcie_tfd_unmap(trans, out_meta,
 					   &txq->tfds[q->write_ptr],
@@ -1286,7 +1328,7 @@ static int iwl_pcie_enqueue_hcmd(struct
 			goto out;
 		}
 
-		iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
+		iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
 	}
 
 	out_meta->flags = cmd->flags;
@@ -1296,8 +1338,7 @@ static int iwl_pcie_enqueue_hcmd(struct
 
 	txq->need_update = 1;
 
-	trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
-			       &out_cmd->hdr, copy_size);
+	trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
 
 	/* start timer if queue currently empty */
 	if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/libertas/if_sdio.c linux-libre-3.8.13-gnu1/drivers/net/wireless/libertas/if_sdio.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/libertas/if_sdio.c	2013-05-01 16:44:38.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/libertas/if_sdio.c	2013-05-11 19:20:29.000000000 -0400
@@ -812,6 +812,11 @@ static void if_sdio_finish_power_on(stru
 
 	sdio_release_host(func);
 
+	/* Set fw_ready before queuing any commands so that
+	 * lbs_thread won't block from sending them to firmware.
+	 */
+	priv->fw_ready = 1;
+
 	/*
 	 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
 	 */
@@ -826,7 +831,6 @@ static void if_sdio_finish_power_on(stru
 			netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
 	}
 
-	priv->fw_ready = 1;
 	wake_up(&card->pwron_waitq);
 
 	if (!card->started) {
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/cfg80211.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/cfg80211.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/cfg80211.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/cfg80211.c	2013-05-11 16:57:46.000000000 -0400
@@ -1846,7 +1846,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiph
 		}
 	}
 
-	for (i = 0; i < request->n_channels; i++) {
+	for (i = 0; i < min_t(u32, request->n_channels,
+			      MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
 		chan = request->channels[i];
 		priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
 		priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/cmdevt.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/cmdevt.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/cmdevt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/cmdevt.c	2013-05-11 16:57:46.000000000 -0400
@@ -156,6 +156,20 @@ static int mwifiex_dnld_cmd_to_fw(struct
 		return -1;
 	}
 
+	cmd_code = le16_to_cpu(host_cmd->command);
+	cmd_size = le16_to_cpu(host_cmd->size);
+
+	if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
+	    cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
+	    cmd_code != HostCmd_CMD_FUNC_INIT) {
+		dev_err(adapter->dev,
+			"DNLD_CMD: FW in reset state, ignore cmd %#x\n",
+			cmd_code);
+		mwifiex_complete_cmd(adapter, cmd_node);
+		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+		return -1;
+	}
+
 	/* Set command sequence number */
 	adapter->seq_num++;
 	host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
@@ -167,9 +181,6 @@ static int mwifiex_dnld_cmd_to_fw(struct
 	adapter->curr_cmd = cmd_node;
 	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
 
-	cmd_code = le16_to_cpu(host_cmd->command);
-	cmd_size = le16_to_cpu(host_cmd->size);
-
 	/* Adjust skb length */
 	if (cmd_node->cmd_skb->len > cmd_size)
 		/*
@@ -488,8 +499,6 @@ int mwifiex_send_cmd_sync(struct mwifiex
 
 	ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
 				     data_buf);
-	if (!ret)
-		ret = mwifiex_wait_queue_complete(adapter);
 
 	return ret;
 }
@@ -592,9 +601,10 @@ int mwifiex_send_cmd_async(struct mwifie
 	if (cmd_no == HostCmd_CMD_802_11_SCAN) {
 		mwifiex_queue_scan_cmd(priv, cmd_node);
 	} else {
-		adapter->cmd_queued = cmd_node;
 		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
 		queue_work(adapter->workqueue, &adapter->main_work);
+		if (cmd_node->wait_q_enabled)
+			ret = mwifiex_wait_queue_complete(adapter, cmd_node);
 	}
 
 	return ret;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/init.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/init.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/init.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/init.c	2013-05-11 16:57:46.000000000 -0400
@@ -707,6 +707,14 @@ mwifiex_shutdown_drv(struct mwifiex_adap
 		return ret;
 	}
 
+	/* cancel current command */
+	if (adapter->curr_cmd) {
+		dev_warn(adapter->dev, "curr_cmd is still in processing\n");
+		del_timer(&adapter->cmd_timer);
+		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
+		adapter->curr_cmd = NULL;
+	}
+
 	/* shut down mwifiex */
 	dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/join.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/join.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/join.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/join.c	2013-05-11 16:57:46.000000000 -0400
@@ -1092,10 +1092,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mw
 		adhoc_join->bss_descriptor.bssid,
 		adhoc_join->bss_descriptor.ssid);
 
-	for (i = 0; bss_desc->supported_rates[i] &&
-			i < MWIFIEX_SUPPORTED_RATES;
-			i++)
-			;
+	for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
+		    bss_desc->supported_rates[i]; i++)
+		;
 	rates_size = i;
 
 	/* Copy Data Rates from the Rates recorded in scan response */
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/main.h linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/main.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/main.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/main.h	2013-05-11 16:57:46.000000000 -0400
@@ -714,7 +714,6 @@ struct mwifiex_adapter {
 	u16 cmd_wait_q_required;
 	struct mwifiex_wait_queue cmd_wait_q;
 	u8 scan_wait_q_woken;
-	struct cmd_ctrl_node *cmd_queued;
 	spinlock_t queue_lock;		/* lock for tx queues */
 	struct completion fw_load;
 	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
@@ -994,7 +993,8 @@ int mwifiex_request_set_multicast_list(s
 			struct mwifiex_multicast_list *mcast_list);
 int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
 			    struct net_device *dev);
-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
+				struct cmd_ctrl_node *cmd_queued);
 int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 		      struct cfg80211_ssid *req_ssid);
 int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/pcie.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/pcie.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/pcie.c	2013-05-01 16:44:57.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/pcie.c	2013-05-11 19:20:47.000000000 -0400
@@ -291,7 +291,7 @@ static int mwifiex_pm_wakeup_card(struct
 		i++;
 		usleep_range(10, 20);
 		/* 50ms max wait */
-		if (i == 50000)
+		if (i == 5000)
 			break;
 	}
 
@@ -1831,9 +1831,9 @@ static void mwifiex_pcie_cleanup(struct
 	if (pdev) {
 		pci_iounmap(pdev, card->pci_mmap);
 		pci_iounmap(pdev, card->pci_mmap1);
-
-		pci_release_regions(pdev);
 		pci_disable_device(pdev);
+		pci_release_region(pdev, 2);
+		pci_release_region(pdev, 0);
 		pci_set_drvdata(pdev, NULL);
 	}
 }
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/scan.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/scan.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/scan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/scan.c	2013-05-11 16:57:46.000000000 -0400
@@ -1366,10 +1366,15 @@ int mwifiex_scan_networks(struct mwifiex
 			list_del(&cmd_node->list);
 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
 					       flags);
-			adapter->cmd_queued = cmd_node;
 			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
 							true);
 			queue_work(adapter->workqueue, &adapter->main_work);
+
+			/* Perform internal scan synchronously */
+			if (!priv->scan_request) {
+				dev_dbg(adapter->dev, "wait internal scan\n");
+				mwifiex_wait_queue_complete(adapter, cmd_node);
+			}
 		} else {
 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
 					       flags);
@@ -1765,7 +1770,12 @@ check_next_scan:
 		/* Need to indicate IOCTL complete */
 		if (adapter->curr_cmd->wait_q_enabled) {
 			adapter->cmd_wait_q.status = 0;
-			mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+			if (!priv->scan_request) {
+				dev_dbg(adapter->dev,
+					"complete internal scan\n");
+				mwifiex_complete_cmd(adapter,
+						     adapter->curr_cmd);
+			}
 		}
 		if (priv->report_scan_result)
 			priv->report_scan_result = false;
@@ -1923,9 +1933,6 @@ int mwifiex_request_scan(struct mwifiex_
 		/* Normal scan */
 		ret = mwifiex_scan_networks(priv, NULL);
 
-	if (!ret)
-		ret = mwifiex_wait_queue_complete(priv->adapter);
-
 	up(&priv->async_sem);
 
 	return ret;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/sta_ioctl.c linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/sta_ioctl.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/mwifiex/sta_ioctl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/mwifiex/sta_ioctl.c	2013-05-11 16:57:46.000000000 -0400
@@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifi
  * This function waits on a cmd wait queue. It also cancels the pending
  * request after waking up, in case of errors.
  */
-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
+				struct cmd_ctrl_node *cmd_queued)
 {
 	int status;
-	struct cmd_ctrl_node *cmd_queued;
-
-	if (!adapter->cmd_queued)
-		return 0;
-
-	cmd_queued = adapter->cmd_queued;
-	adapter->cmd_queued = NULL;
 
 	dev_dbg(adapter->dev, "cmd pending\n");
 	atomic_inc(&adapter->cmd_pending);
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/p54/p54usb.c linux-libre-3.8.13-gnu1/drivers/net/wireless/p54/p54usb.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/p54/p54usb.c	2013-05-01 16:45:26.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/p54/p54usb.c	2013-05-11 19:21:17.000000000 -0400
@@ -83,8 +83,8 @@ static struct usb_device_id p54u_table[]
 	{USB_DEVICE(0x06b9, 0x0121)},	/* Thomson SpeedTouch 121g */
 	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
 	{USB_DEVICE(0x0803, 0x4310)},	/* Zoom 4410a */
-	{USB_DEVICE(0x083a, 0x4503)},	/* T-Com Sinus 154 data II */
 	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
+	{USB_DEVICE(0x083a, 0x4531)},	/* T-Com Sinus 154 data II */
 	{USB_DEVICE(0x083a, 0xc501)},	/* Zoom Wireless-G 4410 */
 	{USB_DEVICE(0x083a, 0xf503)},	/* Accton FD7050E ver 1010ec  */
 	{USB_DEVICE(0x0846, 0x4240)},	/* Netgear WG111 (v2) */
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rt2x00/rt2800lib.c linux-libre-3.8.13-gnu1/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/rt2x00/rt2800lib.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rt2x00/rt2800lib.c	2013-05-11 16:57:46.000000000 -0400
@@ -4386,6 +4386,8 @@ static int rt2800_init_rfcsr(struct rt2x
 
 	if (!rt2x00_rt(rt2x00dev, RT5390) &&
 	    !rt2x00_rt(rt2x00dev, RT5392)) {
+		u8 min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2;
+
 		rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
 		rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
 		if (rt2x00_rt(rt2x00dev, RT3070) ||
@@ -4396,8 +4398,10 @@ static int rt2800_init_rfcsr(struct rt2x
 				      &rt2x00dev->cap_flags))
 				rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
 		}
-		rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
-				  drv_data->txmixer_gain_24g);
+		if (drv_data->txmixer_gain_24g >= min_gain) {
+			rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+					  drv_data->txmixer_gain_24g);
+		}
 		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rt2x00/rt2x00dev.c linux-libre-3.8.13-gnu1/drivers/net/wireless/rt2x00/rt2x00dev.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/rt2x00/rt2x00dev.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rt2x00/rt2x00dev.c	2013-05-11 16:57:46.000000000 -0400
@@ -1209,7 +1209,9 @@ int rt2x00lib_probe_dev(struct rt2x00_de
 		rt2x00dev->hw->wiphy->interface_modes |=
 		    BIT(NL80211_IFTYPE_ADHOC) |
 		    BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
 		    BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
 		    BIT(NL80211_IFTYPE_WDS);
 
 	rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rt2x00/rt2x00pci.c linux-libre-3.8.13-gnu1/drivers/net/wireless/rt2x00/rt2x00pci.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/rt2x00/rt2x00pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rt2x00/rt2x00pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -52,8 +52,8 @@ int rt2x00pci_regbusy_read(struct rt2x00
 		udelay(REGISTER_BUSY_DELAY);
 	}
 
-	ERROR(rt2x00dev, "Indirect register access failed: "
-	      "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+	printk_once(KERN_ERR "%s() Indirect register access failed: "
+	      "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
 	*reg = ~0;
 
 	return 0;
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2013-05-11 16:57:46.000000000 -0400
@@ -1377,74 +1377,57 @@ void rtl92cu_card_disable(struct ieee802
 
 void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
 {
-	/* dummy routine needed for callback from rtl_op_configure_filter() */
-}
-
-/*========================================================================== */
-
-static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
-			      enum nl80211_iftype type)
-{
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	u8 filterout_non_associated_bssid = false;
+	u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
 
-	switch (type) {
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_STATION:
-		filterout_non_associated_bssid = true;
-		break;
-	case NL80211_IFTYPE_UNSPECIFIED:
-	case NL80211_IFTYPE_AP:
-	default:
-		break;
-	}
-	if (filterout_non_associated_bssid) {
+	if (rtlpriv->psc.rfpwr_state != ERFON)
+		return;
+
+	if (check_bssid) {
+		u8 tmp;
 		if (IS_NORMAL_CHIP(rtlhal->version)) {
-			switch (rtlphy->current_io_type) {
-			case IO_CMD_RESUME_DM_BY_SCAN:
-				reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
-				rtlpriv->cfg->ops->set_hw_reg(hw,
-						 HW_VAR_RCR, (u8 *)(&reg_rcr));
-				/* enable update TSF */
-				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
-				break;
-			case IO_CMD_PAUSE_DM_BY_SCAN:
-				reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
-				rtlpriv->cfg->ops->set_hw_reg(hw,
-						 HW_VAR_RCR, (u8 *)(&reg_rcr));
-				/* disable update TSF */
-				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
-				break;
-			}
+			reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+			tmp = BIT(4);
 		} else {
-			reg_rcr |= (RCR_CBSSID);
-			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-						      (u8 *)(&reg_rcr));
-			_rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
+			reg_rcr |= RCR_CBSSID;
+			tmp = BIT(4) | BIT(5);
 		}
-	} else if (filterout_non_associated_bssid == false) {
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+					      (u8 *) (&reg_rcr));
+		_rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
+	} else {
+		u8 tmp;
 		if (IS_NORMAL_CHIP(rtlhal->version)) {
-			reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
-			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-						      (u8 *)(&reg_rcr));
-			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+			reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+			tmp = BIT(4);
 		} else {
-			reg_rcr &= (~RCR_CBSSID);
-			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-						      (u8 *)(&reg_rcr));
-			_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
+			reg_rcr &= ~RCR_CBSSID;
+			tmp = BIT(4) | BIT(5);
 		}
+		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+		rtlpriv->cfg->ops->set_hw_reg(hw,
+					      HW_VAR_RCR, (u8 *) (&reg_rcr));
+		_rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0);
 	}
 }
 
+/*========================================================================== */
+
 int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
 {
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
 	if (_rtl92cu_set_media_status(hw, type))
 		return -EOPNOTSUPP;
-	_rtl92cu_set_check_bssid(hw, type);
+
+	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+		if (type != NL80211_IFTYPE_AP)
+			rtl92cu_set_check_bssid(hw, true);
+	} else {
+		rtl92cu_set_check_bssid(hw, false);
+	}
+
 	return 0;
 }
 
@@ -2058,8 +2041,6 @@ void rtl92cu_update_hal_rate_table(struc
 			       (shortgi_rate << 4) | (shortgi_rate);
 	}
 	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
-	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
-		 rtl_read_dword(rtlpriv, REG_ARFR0));
 }
 
 void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2013-05-01 16:45:53.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2013-05-11 19:21:43.000000000 -0400
@@ -285,6 +285,7 @@ static struct usb_device_id rtl8192c_usb
 	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
 	/* RTL8188CUS-VL */
 	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)},
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)},
 	/* 8188 Combo for BC4 */
 	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
 
@@ -363,9 +364,15 @@ static struct usb_device_id rtl8192c_usb
 
 MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids);
 
+static int rtl8192cu_probe(struct usb_interface *intf,
+			   const struct usb_device_id *id)
+{
+	return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg);
+}
+
 static struct usb_driver rtl8192cu_driver = {
 	.name = "rtl8192cu",
-	.probe = rtl_usb_probe,
+	.probe = rtl8192cu_probe,
 	.disconnect = rtl_usb_disconnect,
 	.id_table = rtl8192c_usb_ids,
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/usb.c linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/usb.c
--- linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/usb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/usb.c	2013-05-11 16:57:46.000000000 -0400
@@ -42,8 +42,12 @@
 
 static void usbctrl_async_callback(struct urb *urb)
 {
-	if (urb)
-		kfree(urb->context);
+	if (urb) {
+		/* free dr */
+		kfree(urb->setup_packet);
+		/* free databuf */
+		kfree(urb->transfer_buffer);
+	}
 }
 
 static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
@@ -55,39 +59,47 @@ static int _usbctrl_vendorreq_async_writ
 	u8 reqtype;
 	struct usb_ctrlrequest *dr;
 	struct urb *urb;
-	struct rtl819x_async_write_data {
-		u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE];
-		struct usb_ctrlrequest dr;
-	} *buf;
+	const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE;
+	u8 *databuf;
+
+	if (WARN_ON_ONCE(len > databuf_maxlen))
+		len = databuf_maxlen;
 
 	pipe = usb_sndctrlpipe(udev, 0); /* write_out */
 	reqtype =  REALTEK_USB_VENQT_WRITE;
 
-	buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
-	if (!buf)
+	dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+	if (!dr)
+		return -ENOMEM;
+
+	databuf = kmalloc(databuf_maxlen, GFP_ATOMIC);
+	if (!databuf) {
+		kfree(dr);
 		return -ENOMEM;
+	}
 
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
-		kfree(buf);
+		kfree(databuf);
+		kfree(dr);
 		return -ENOMEM;
 	}
 
-	dr = &buf->dr;
-
 	dr->bRequestType = reqtype;
 	dr->bRequest = request;
 	dr->wValue = cpu_to_le16(value);
 	dr->wIndex = cpu_to_le16(index);
 	dr->wLength = cpu_to_le16(len);
 	/* data are already in little-endian order */
-	memcpy(buf, pdata, len);
+	memcpy(databuf, pdata, len);
 	usb_fill_control_urb(urb, udev, pipe,
-			     (unsigned char *)dr, buf, len,
-			     usbctrl_async_callback, buf);
+			     (unsigned char *)dr, databuf, len,
+			     usbctrl_async_callback, NULL);
 	rc = usb_submit_urb(urb, GFP_ATOMIC);
-	if (rc < 0)
-		kfree(buf);
+	if (rc < 0) {
+		kfree(databuf);
+		kfree(dr);
+	}
 	usb_free_urb(urb);
 	return rc;
 }
@@ -842,6 +854,7 @@ static void _rtl_usb_transmit(struct iee
 	if (unlikely(!_urb)) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "Can't allocate urb. Drop skb!\n");
+		kfree_skb(skb);
 		return;
 	}
 	urb_list = &rtlusb->tx_pending[ep_num];
@@ -941,7 +954,8 @@ static struct rtl_intf_ops rtl_usb_ops =
 };
 
 int rtl_usb_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
+		  const struct usb_device_id *id,
+		  struct rtl_hal_cfg *rtl_hal_cfg)
 {
 	int err;
 	struct ieee80211_hw *hw = NULL;
@@ -976,7 +990,7 @@ int rtl_usb_probe(struct usb_interface *
 	usb_set_intfdata(intf, hw);
 	/* init cfg & intf_ops */
 	rtlpriv->rtlhal.interface = INTF_USB;
-	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info);
+	rtlpriv->cfg = rtl_hal_cfg;
 	rtlpriv->intf_ops = &rtl_usb_ops;
 	rtl_dbgp_flag_init(hw);
 	/* Init IO handler */
diff -druNp linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/usb.h linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/usb.h
--- linux-libre-3.8-gnu1/drivers/net/wireless/rtlwifi/usb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/wireless/rtlwifi/usb.h	2013-05-11 16:57:46.000000000 -0400
@@ -157,7 +157,8 @@ struct rtl_usb_priv {
 
 
 int rtl_usb_probe(struct usb_interface *intf,
-			    const struct usb_device_id *id);
+		  const struct usb_device_id *id,
+		  struct rtl_hal_cfg *rtl92cu_hal_cfg);
 void rtl_usb_disconnect(struct usb_interface *intf);
 int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
 int rtl_usb_resume(struct usb_interface *pusb_intf);
diff -druNp linux-libre-3.8-gnu1/drivers/net/xen-netback/interface.c linux-libre-3.8.13-gnu1/drivers/net/xen-netback/interface.c
--- linux-libre-3.8-gnu1/drivers/net/xen-netback/interface.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/xen-netback/interface.c	2013-05-11 16:57:46.000000000 -0400
@@ -132,6 +132,7 @@ static void xenvif_up(struct xenvif *vif
 static void xenvif_down(struct xenvif *vif)
 {
 	disable_irq(vif->irq);
+	del_timer_sync(&vif->credit_timeout);
 	xen_netbk_deschedule_xenvif(vif);
 	xen_netbk_remove_xenvif(vif);
 }
@@ -363,8 +364,6 @@ void xenvif_disconnect(struct xenvif *vi
 	atomic_dec(&vif->refcnt);
 	wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
 
-	del_timer_sync(&vif->credit_timeout);
-
 	if (vif->irq)
 		unbind_from_irqhandler(vif->irq, vif);
 
diff -druNp linux-libre-3.8-gnu1/drivers/net/xen-netback/netback.c linux-libre-3.8.13-gnu1/drivers/net/xen-netback/netback.c
--- linux-libre-3.8-gnu1/drivers/net/xen-netback/netback.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/net/xen-netback/netback.c	2013-05-11 16:57:46.000000000 -0400
@@ -911,13 +911,13 @@ static int netbk_count_requests(struct x
 		if (frags >= work_to_do) {
 			netdev_err(vif->dev, "Need more frags\n");
 			netbk_fatal_tx_err(vif);
-			return -frags;
+			return -ENODATA;
 		}
 
 		if (unlikely(frags >= MAX_SKB_FRAGS)) {
 			netdev_err(vif->dev, "Too many frags\n");
 			netbk_fatal_tx_err(vif);
-			return -frags;
+			return -E2BIG;
 		}
 
 		memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
@@ -925,7 +925,7 @@ static int netbk_count_requests(struct x
 		if (txp->size > first->size) {
 			netdev_err(vif->dev, "Frag is bigger than frame.\n");
 			netbk_fatal_tx_err(vif);
-			return -frags;
+			return -EIO;
 		}
 
 		first->size -= txp->size;
@@ -935,7 +935,7 @@ static int netbk_count_requests(struct x
 			netdev_err(vif->dev, "txp->offset: %x, size: %u\n",
 				 txp->offset, txp->size);
 			netbk_fatal_tx_err(vif);
-			return -frags;
+			return -EINVAL;
 		}
 	} while ((txp++)->flags & XEN_NETTXF_more_data);
 	return frags;
diff -druNp linux-libre-3.8-gnu1/drivers/pci/access.c linux-libre-3.8.13-gnu1/drivers/pci/access.c
--- linux-libre-3.8-gnu1/drivers/pci/access.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pci/access.c	2013-05-11 16:57:46.000000000 -0400
@@ -515,7 +515,7 @@ static bool pcie_capability_reg_implemen
 		return false;
 
 	switch (pos) {
-	case PCI_EXP_FLAGS_TYPE:
+	case PCI_EXP_FLAGS:
 		return true;
 	case PCI_EXP_DEVCAP:
 	case PCI_EXP_DEVCTL:
diff -druNp linux-libre-3.8-gnu1/drivers/pci/pci-acpi.c linux-libre-3.8.13-gnu1/drivers/pci/pci-acpi.c
--- linux-libre-3.8-gnu1/drivers/pci/pci-acpi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pci/pci-acpi.c	2013-05-11 16:57:46.000000000 -0400
@@ -53,14 +53,15 @@ static void pci_acpi_wake_dev(acpi_handl
 		return;
 	}
 
-	if (!pci_dev->pm_cap || !pci_dev->pme_support
-	     || pci_check_pme_status(pci_dev)) {
-		if (pci_dev->pme_poll)
-			pci_dev->pme_poll = false;
+	/* Clear PME Status if set. */
+	if (pci_dev->pme_support)
+		pci_check_pme_status(pci_dev);
 
-		pci_wakeup_event(pci_dev);
-		pm_runtime_resume(&pci_dev->dev);
-	}
+	if (pci_dev->pme_poll)
+		pci_dev->pme_poll = false;
+
+	pci_wakeup_event(pci_dev);
+	pm_runtime_resume(&pci_dev->dev);
 
 	if (pci_dev->subordinate)
 		pci_pme_wakeup_bus(pci_dev->subordinate);
diff -druNp linux-libre-3.8-gnu1/drivers/pci/pci.c linux-libre-3.8.13-gnu1/drivers/pci/pci.c
--- linux-libre-3.8-gnu1/drivers/pci/pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pci/pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -651,15 +651,11 @@ static int pci_platform_power_transition
 		error = platform_pci_set_power_state(dev, state);
 		if (!error)
 			pci_update_current_state(dev, state);
-		/* Fall back to PCI_D0 if native PM is not supported */
-		if (!dev->pm_cap)
-			dev->current_state = PCI_D0;
-	} else {
+	} else
 		error = -ENODEV;
-		/* Fall back to PCI_D0 if native PM is not supported */
-		if (!dev->pm_cap)
-			dev->current_state = PCI_D0;
-	}
+
+	if (error && !dev->pm_cap) /* Fall back to PCI_D0 */
+		dev->current_state = PCI_D0;
 
 	return error;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/pci/pci-driver.c linux-libre-3.8.13-gnu1/drivers/pci/pci-driver.c
--- linux-libre-3.8-gnu1/drivers/pci/pci-driver.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pci/pci-driver.c	2013-05-11 16:57:46.000000000 -0400
@@ -628,6 +628,7 @@ static int pci_pm_suspend(struct device
 		goto Fixup;
 	}
 
+	pci_dev->state_saved = false;
 	if (pm->suspend) {
 		pci_power_t prev = pci_dev->current_state;
 		int error;
@@ -774,6 +775,7 @@ static int pci_pm_freeze(struct device *
 		return 0;
 	}
 
+	pci_dev->state_saved = false;
 	if (pm->freeze) {
 		int error;
 
@@ -862,6 +864,7 @@ static int pci_pm_poweroff(struct device
 		goto Fixup;
 	}
 
+	pci_dev->state_saved = false;
 	if (pm->poweroff) {
 		int error;
 
@@ -987,6 +990,7 @@ static int pci_pm_runtime_suspend(struct
 	if (!pm || !pm->runtime_suspend)
 		return -ENOSYS;
 
+	pci_dev->state_saved = false;
 	pci_dev->no_d3cold = false;
 	error = pm->runtime_suspend(dev);
 	suspend_report_result(pm->runtime_suspend, error);
diff -druNp linux-libre-3.8-gnu1/drivers/pci/pcie/portdrv_pci.c linux-libre-3.8.13-gnu1/drivers/pci/pcie/portdrv_pci.c
--- linux-libre-3.8-gnu1/drivers/pci/pcie/portdrv_pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pci/pcie/portdrv_pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -185,14 +185,6 @@ static const struct dev_pm_ops pcie_port
 #endif /* !PM */
 
 /*
- * PCIe port runtime suspend is broken for some chipsets, so use a
- * black list to disable runtime PM for these chipsets.
- */
-static const struct pci_device_id port_runtime_pm_black_list[] = {
-	{ /* end: all zeroes */ }
-};
-
-/*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
  *
@@ -225,16 +217,11 @@ static int pcie_portdrv_probe(struct pci
 	 * it by default.
 	 */
 	dev->d3cold_allowed = false;
-	if (!pci_match_id(port_runtime_pm_black_list, dev))
-		pm_runtime_put_noidle(&dev->dev);
-
 	return 0;
 }
 
 static void pcie_portdrv_remove(struct pci_dev *dev)
 {
-	if (!pci_match_id(port_runtime_pm_black_list, dev))
-		pm_runtime_get_noresume(&dev->dev);
 	pcie_port_device_remove(dev);
 	pci_disable_device(dev);
 }
diff -druNp linux-libre-3.8-gnu1/drivers/pcmcia/vrc4171_card.c linux-libre-3.8.13-gnu1/drivers/pcmcia/vrc4171_card.c
--- linux-libre-3.8-gnu1/drivers/pcmcia/vrc4171_card.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pcmcia/vrc4171_card.c	2013-05-11 16:57:46.000000000 -0400
@@ -246,6 +246,7 @@ static int pccard_init(struct pcmcia_soc
 	socket = &vrc4171_sockets[slot];
 	socket->csc_irq = search_nonuse_irq();
 	socket->io_irq = search_nonuse_irq();
+	spin_lock_init(&socket->lock);
 
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/platform/x86/acer-wmi.c linux-libre-3.8.13-gnu1/drivers/platform/x86/acer-wmi.c
--- linux-libre-3.8-gnu1/drivers/platform/x86/acer-wmi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/platform/x86/acer-wmi.c	2013-05-11 16:57:46.000000000 -0400
@@ -1204,6 +1204,9 @@ static acpi_status WMID_set_capabilities
 			devices = *((u32 *) obj->buffer.pointer);
 		} else if (obj->type == ACPI_TYPE_INTEGER) {
 			devices = (u32) obj->integer.value;
+		} else {
+			kfree(out.pointer);
+			return AE_ERROR;
 		}
 	} else {
 		kfree(out.pointer);
diff -druNp linux-libre-3.8-gnu1/drivers/platform/x86/msi-wmi.c linux-libre-3.8.13-gnu1/drivers/platform/x86/msi-wmi.c
--- linux-libre-3.8-gnu1/drivers/platform/x86/msi-wmi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/platform/x86/msi-wmi.c	2013-05-11 16:57:46.000000000 -0400
@@ -176,7 +176,7 @@ static void msi_wmi_notify(u32 value, vo
 				pr_debug("Suppressed key event 0x%X - "
 					 "Last press was %lld us ago\n",
 					 key->code, ktime_to_us(diff));
-				return;
+				goto msi_wmi_notify_exit;
 			}
 			last_pressed[key->code - SCANCODE_BASE] = cur;
 
@@ -195,6 +195,8 @@ static void msi_wmi_notify(u32 value, vo
 			pr_info("Unknown key pressed - %x\n", eventcode);
 	} else
 		pr_info("Unknown event received\n");
+
+msi_wmi_notify_exit:
 	kfree(response.pointer);
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/platform/x86/sony-laptop.c linux-libre-3.8.13-gnu1/drivers/platform/x86/sony-laptop.c
--- linux-libre-3.8-gnu1/drivers/platform/x86/sony-laptop.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/platform/x86/sony-laptop.c	2013-05-11 16:57:46.000000000 -0400
@@ -1534,7 +1534,7 @@ static int sony_nc_rfkill_set(void *data
 	int argument = sony_rfkill_address[(long) data] + 0x100;
 
 	if (!blocked)
-		argument |= 0x030000;
+		argument |= 0x070000;
 
 	return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
 }
diff -druNp linux-libre-3.8-gnu1/drivers/power/ab8500_btemp.c linux-libre-3.8.13-gnu1/drivers/power/ab8500_btemp.c
--- linux-libre-3.8-gnu1/drivers/power/ab8500_btemp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/power/ab8500_btemp.c	2013-05-11 16:57:46.000000000 -0400
@@ -1123,7 +1123,7 @@ static void __exit ab8500_btemp_exit(voi
 	platform_driver_unregister(&ab8500_btemp_driver);
 }
 
-subsys_initcall_sync(ab8500_btemp_init);
+device_initcall(ab8500_btemp_init);
 module_exit(ab8500_btemp_exit);
 
 MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-3.8-gnu1/drivers/power/abx500_chargalg.c linux-libre-3.8.13-gnu1/drivers/power/abx500_chargalg.c
--- linux-libre-3.8-gnu1/drivers/power/abx500_chargalg.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/power/abx500_chargalg.c	2013-05-11 16:57:46.000000000 -0400
@@ -1698,7 +1698,7 @@ static ssize_t abx500_chargalg_sysfs_cha
 static struct attribute abx500_chargalg_en_charger = \
 {
 	.name = "chargalg",
-	.mode = S_IWUGO,
+	.mode = S_IWUSR,
 };
 
 static struct attribute *abx500_chargalg_chg[] = {
diff -druNp linux-libre-3.8-gnu1/drivers/power/bq27x00_battery.c linux-libre-3.8.13-gnu1/drivers/power/bq27x00_battery.c
--- linux-libre-3.8-gnu1/drivers/power/bq27x00_battery.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/power/bq27x00_battery.c	2013-05-11 16:57:46.000000000 -0400
@@ -448,7 +448,6 @@ static void bq27x00_update(struct bq27x0
 		cache.temperature = bq27x00_battery_read_temperature(di);
 		if (!is_bq27425)
 			cache.cycle_count = bq27x00_battery_read_cyct(di);
-		cache.cycle_count = bq27x00_battery_read_cyct(di);
 		cache.power_avg =
 			bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG);
 
@@ -696,7 +695,6 @@ static int bq27x00_powersupply_init(stru
 	int ret;
 
 	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
-	di->chip = BQ27425;
 	if (di->chip == BQ27425) {
 		di->bat.properties = bq27425_battery_props;
 		di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props);
diff -druNp linux-libre-3.8-gnu1/drivers/pps/clients/pps-ldisc.c linux-libre-3.8.13-gnu1/drivers/pps/clients/pps-ldisc.c
--- linux-libre-3.8-gnu1/drivers/pps/clients/pps-ldisc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pps/clients/pps-ldisc.c	2013-05-11 16:57:46.000000000 -0400
@@ -31,7 +31,7 @@
 static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status,
 				struct pps_event_time *ts)
 {
-	struct pps_device *pps = (struct pps_device *)tty->disc_data;
+	struct pps_device *pps = pps_lookup_dev(tty);
 
 	BUG_ON(pps == NULL);
 
@@ -67,9 +67,9 @@ static int pps_tty_open(struct tty_struc
 		pr_err("cannot register PPS source \"%s\"\n", info.path);
 		return -ENOMEM;
 	}
-	tty->disc_data = pps;
+	pps->lookup_cookie = tty;
 
-	/* Should open N_TTY ldisc too */
+	/* Now open the base class N_TTY ldisc */
 	ret = alias_n_tty_open(tty);
 	if (ret < 0) {
 		pr_err("cannot open tty ldisc \"%s\"\n", info.path);
@@ -81,7 +81,6 @@ static int pps_tty_open(struct tty_struc
 	return 0;
 
 err_unregister:
-	tty->disc_data = NULL;
 	pps_unregister_source(pps);
 	return ret;
 }
@@ -90,11 +89,10 @@ static void (*alias_n_tty_close)(struct
 
 static void pps_tty_close(struct tty_struct *tty)
 {
-	struct pps_device *pps = (struct pps_device *)tty->disc_data;
+	struct pps_device *pps = pps_lookup_dev(tty);
 
 	alias_n_tty_close(tty);
 
-	tty->disc_data = NULL;
 	dev_info(pps->dev, "removed\n");
 	pps_unregister_source(pps);
 }
diff -druNp linux-libre-3.8-gnu1/drivers/pps/pps.c linux-libre-3.8.13-gnu1/drivers/pps/pps.c
--- linux-libre-3.8-gnu1/drivers/pps/pps.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pps/pps.c	2013-05-11 16:57:46.000000000 -0400
@@ -247,12 +247,15 @@ static int pps_cdev_open(struct inode *i
 	struct pps_device *pps = container_of(inode->i_cdev,
 						struct pps_device, cdev);
 	file->private_data = pps;
-
+	kobject_get(&pps->dev->kobj);
 	return 0;
 }
 
 static int pps_cdev_release(struct inode *inode, struct file *file)
 {
+	struct pps_device *pps = container_of(inode->i_cdev,
+						struct pps_device, cdev);
+	kobject_put(&pps->dev->kobj);
 	return 0;
 }
 
@@ -274,8 +277,10 @@ static void pps_device_destruct(struct d
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
-	/* release id here to protect others from using it while it's
-	 * still in use */
+	cdev_del(&pps->cdev);
+
+	/* Now we can release the ID for re-use */
+	pr_debug("deallocating pps%d\n", pps->id);
 	mutex_lock(&pps_idr_lock);
 	idr_remove(&pps_idr, pps->id);
 	mutex_unlock(&pps_idr_lock);
@@ -332,6 +337,7 @@ int pps_register_cdev(struct pps_device
 		goto del_cdev;
 	}
 
+	/* Override the release function with our own */
 	pps->dev->release = pps_device_destruct;
 
 	pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
@@ -352,11 +358,44 @@ free_idr:
 
 void pps_unregister_cdev(struct pps_device *pps)
 {
+	pr_debug("unregistering pps%d\n", pps->id);
+	pps->lookup_cookie = NULL;
 	device_destroy(pps_class, pps->dev->devt);
-	cdev_del(&pps->cdev);
 }
 
 /*
+ * Look up a pps device by magic cookie.
+ * The cookie is usually a pointer to some enclosing device, but this
+ * code doesn't care; you should never be dereferencing it.
+ *
+ * This is a bit of a kludge that is currently used only by the PPS
+ * serial line discipline.  It may need to be tweaked when a second user
+ * is found.
+ *
+ * There is no function interface for setting the lookup_cookie field.
+ * It's initialized to NULL when the pps device is created, and if a
+ * client wants to use it, just fill it in afterward.
+ *
+ * The cookie is automatically set to NULL in pps_unregister_source()
+ * so that it will not be used again, even if the pps device cannot
+ * be removed from the idr due to pending references holding the minor
+ * number in use.
+ */
+struct pps_device *pps_lookup_dev(void const *cookie)
+{
+	struct pps_device *pps;
+	unsigned id;
+
+	rcu_read_lock();
+	idr_for_each_entry(&pps_idr, pps, id)
+		if (cookie == pps->lookup_cookie)
+			break;
+	rcu_read_unlock();
+	return pps;
+}
+EXPORT_SYMBOL(pps_lookup_dev);
+
+/*
  * Module stuff
  */
 
diff -druNp linux-libre-3.8-gnu1/drivers/pwm/pwm-spear.c linux-libre-3.8.13-gnu1/drivers/pwm/pwm-spear.c
--- linux-libre-3.8-gnu1/drivers/pwm/pwm-spear.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/pwm/pwm-spear.c	2013-05-11 16:57:46.000000000 -0400
@@ -143,7 +143,7 @@ static int spear_pwm_enable(struct pwm_c
 	u32 val;
 
 	rc = clk_enable(pc->clk);
-	if (!rc)
+	if (rc)
 		return rc;
 
 	val = spear_pwm_readl(pc, pwm->hwpwm, PWMCR);
@@ -209,12 +209,12 @@ static int spear_pwm_probe(struct platfo
 	pc->chip.npwm = NUM_PWM;
 
 	ret = clk_prepare(pc->clk);
-	if (!ret)
+	if (ret)
 		return ret;
 
 	if (of_device_is_compatible(np, "st,spear1340-pwm")) {
 		ret = clk_enable(pc->clk);
-		if (!ret) {
+		if (ret) {
 			clk_unprepare(pc->clk);
 			return ret;
 		}
diff -druNp linux-libre-3.8-gnu1/drivers/regulator/core.c linux-libre-3.8.13-gnu1/drivers/regulator/core.c
--- linux-libre-3.8-gnu1/drivers/regulator/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/regulator/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -200,8 +200,8 @@ static int regulator_check_consumers(str
 	}
 
 	if (*min_uV > *max_uV) {
-		dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
-			regulator->min_uV, regulator->max_uV);
+		rdev_err(rdev, "Restricting voltage, %u-%uuV\n",
+			*min_uV, *max_uV);
 		return -EINVAL;
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/remoteproc/Kconfig linux-libre-3.8.13-gnu1/drivers/remoteproc/Kconfig
--- linux-libre-3.8-gnu1/drivers/remoteproc/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/remoteproc/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -5,7 +5,7 @@ config REMOTEPROC
 	tristate
 	depends on EXPERIMENTAL
 	depends on HAS_DMA
-	select FW_CONFIG
+	select FW_LOADER
 	select VIRTIO
 
 config OMAP_REMOTEPROC
diff -druNp linux-libre-3.8-gnu1/drivers/remoteproc/remoteproc_core.c linux-libre-3.8.13-gnu1/drivers/remoteproc/remoteproc_core.c
--- linux-libre-3.8-gnu1/drivers/remoteproc/remoteproc_core.c	2013-05-01 16:48:53.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/remoteproc/remoteproc_core.c	2013-05-11 19:24:41.000000000 -0400
@@ -370,10 +370,12 @@ static int rproc_handle_vdev(struct rpro
 	/* it is now safe to add the virtio device */
 	ret = rproc_add_virtio_dev(rvdev, rsc->id);
 	if (ret)
-		goto free_rvdev;
+		goto remove_rvdev;
 
 	return 0;
 
+remove_rvdev:
+	list_del(&rvdev->node);
 free_rvdev:
 	kfree(rvdev);
 	return ret;
diff -druNp linux-libre-3.8-gnu1/drivers/remoteproc/ste_modem_rproc.c linux-libre-3.8.13-gnu1/drivers/remoteproc/ste_modem_rproc.c
--- linux-libre-3.8-gnu1/drivers/remoteproc/ste_modem_rproc.c	2013-05-01 16:48:53.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/remoteproc/ste_modem_rproc.c	2013-05-11 19:24:41.000000000 -0400
@@ -240,6 +240,8 @@ static int sproc_drv_remove(struct platf
 
 	/* Unregister as remoteproc device */
 	rproc_del(sproc->rproc);
+	dma_free_coherent(sproc->rproc->dev.parent, SPROC_FW_SIZE,
+			  sproc->fw_addr, sproc->fw_dma_addr);
 	rproc_put(sproc->rproc);
 
 	mdev->drv_data = NULL;
@@ -297,10 +299,13 @@ static int sproc_probe(struct platform_d
 	/* Register as a remoteproc device */
 	err = rproc_add(rproc);
 	if (err)
-		goto free_rproc;
+		goto free_mem;
 
 	return 0;
 
+free_mem:
+	dma_free_coherent(rproc->dev.parent, SPROC_FW_SIZE,
+			  sproc->fw_addr, sproc->fw_dma_addr);
 free_rproc:
 	/* Reset device data upon error */
 	mdev->drv_data = NULL;
diff -druNp linux-libre-3.8-gnu1/drivers/rtc/rtc-cmos.c linux-libre-3.8.13-gnu1/drivers/rtc/rtc-cmos.c
--- linux-libre-3.8-gnu1/drivers/rtc/rtc-cmos.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/rtc/rtc-cmos.c	2013-05-11 16:57:46.000000000 -0400
@@ -805,9 +805,8 @@ static int cmos_suspend(struct device *d
 			mask = RTC_IRQMASK;
 		tmp &= ~mask;
 		CMOS_WRITE(tmp, RTC_CONTROL);
+		hpet_mask_rtc_irq_bit(mask);
 
-		/* shut down hpet emulation - we don't need it for alarm */
-		hpet_mask_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
 		cmos_checkintr(cmos, tmp);
 	}
 	spin_unlock_irq(&rtc_lock);
@@ -872,6 +871,7 @@ static int cmos_resume(struct device *de
 			rtc_update_irq(cmos->rtc, 1, mask);
 			tmp &= ~RTC_AIE;
 			hpet_mask_rtc_irq_bit(RTC_AIE);
+			hpet_rtc_timer_init();
 		} while (mask & RTC_AIE);
 		spin_unlock_irq(&rtc_lock);
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/rtc/rtc-mv.c linux-libre-3.8.13-gnu1/drivers/rtc/rtc-mv.c
--- linux-libre-3.8-gnu1/drivers/rtc/rtc-mv.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/rtc/rtc-mv.c	2013-05-11 16:57:46.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
 
@@ -41,6 +42,7 @@ struct rtc_plat_data {
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;
 	int		irq;
+	struct clk	*clk;
 };
 
 static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -221,6 +223,7 @@ static int mv_rtc_probe(struct platform_
 	struct rtc_plat_data *pdata;
 	resource_size_t size;
 	u32 rtc_time;
+	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -239,11 +242,17 @@ static int mv_rtc_probe(struct platform_
 	if (!pdata->ioaddr)
 		return -ENOMEM;
 
+	pdata->clk = devm_clk_get(&pdev->dev, NULL);
+	/* Not all SoCs require a clock.*/
+	if (!IS_ERR(pdata->clk))
+		clk_prepare_enable(pdata->clk);
+
 	/* make sure the 24 hours mode is enabled */
 	rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
 	if (rtc_time & RTC_HOURS_12H_MODE) {
 		dev_err(&pdev->dev, "24 Hours mode not supported.\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	/* make sure it is actually functional */
@@ -252,7 +261,8 @@ static int mv_rtc_probe(struct platform_
 		rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
 		if (rtc_time == 0x01000000) {
 			dev_err(&pdev->dev, "internal RTC not ticking\n");
-			return -ENODEV;
+			ret = -ENODEV;
+			goto out;
 		}
 	}
 
@@ -268,8 +278,10 @@ static int mv_rtc_probe(struct platform_
 	} else
 		pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
 						 &mv_rtc_ops, THIS_MODULE);
-	if (IS_ERR(pdata->rtc))
-		return PTR_ERR(pdata->rtc);
+	if (IS_ERR(pdata->rtc)) {
+		ret = PTR_ERR(pdata->rtc);
+		goto out;
+	}
 
 	if (pdata->irq >= 0) {
 		writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
@@ -282,6 +294,11 @@ static int mv_rtc_probe(struct platform_
 	}
 
 	return 0;
+out:
+	if (!IS_ERR(pdata->clk))
+		clk_disable_unprepare(pdata->clk);
+
+	return ret;
 }
 
 static int __exit mv_rtc_remove(struct platform_device *pdev)
@@ -292,6 +309,9 @@ static int __exit mv_rtc_remove(struct p
 		device_init_wakeup(&pdev->dev, 0);
 
 	rtc_device_unregister(pdata->rtc);
+	if (!IS_ERR(pdata->clk))
+		clk_disable_unprepare(pdata->clk);
+
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/s390/char/sclp_cmd.c linux-libre-3.8.13-gnu1/drivers/s390/char/sclp_cmd.c
--- linux-libre-3.8-gnu1/drivers/s390/char/sclp_cmd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/s390/char/sclp_cmd.c	2013-05-11 16:57:46.000000000 -0400
@@ -567,6 +567,8 @@ static void __init sclp_add_standby_memo
 	add_memory_merged(0);
 }
 
+#define MEM_SCT_SIZE (1UL << SECTION_SIZE_BITS)
+
 static void __init insert_increment(u16 rn, int standby, int assigned)
 {
 	struct memory_increment *incr, *new_incr;
@@ -579,7 +581,7 @@ static void __init insert_increment(u16
 	new_incr->rn = rn;
 	new_incr->standby = standby;
 	if (!standby)
-		new_incr->usecount = 1;
+		new_incr->usecount = rzm > MEM_SCT_SIZE ? rzm/MEM_SCT_SIZE : 1;
 	last_rn = 0;
 	prev = &sclp_mem_list;
 	list_for_each_entry(incr, &sclp_mem_list, list) {
diff -druNp linux-libre-3.8-gnu1/drivers/s390/kvm/kvm_virtio.c linux-libre-3.8.13-gnu1/drivers/s390/kvm/kvm_virtio.c
--- linux-libre-3.8-gnu1/drivers/s390/kvm/kvm_virtio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/s390/kvm/kvm_virtio.c	2013-05-11 16:57:46.000000000 -0400
@@ -422,6 +422,26 @@ static void kvm_extint_handler(struct ex
 }
 
 /*
+ * For s390-virtio, we expect a page above main storage containing
+ * the virtio configuration. Try to actually load from this area
+ * in order to figure out if the host provides this page.
+ */
+static int __init test_devices_support(unsigned long addr)
+{
+	int ret = -EIO;
+
+	asm volatile(
+		"0:	lura	0,%1\n"
+		"1:	xgr	%0,%0\n"
+		"2:\n"
+		EX_TABLE(0b,2b)
+		EX_TABLE(1b,2b)
+		: "+d" (ret)
+		: "a" (addr)
+		: "0", "cc");
+	return ret;
+}
+/*
  * Init function for virtio
  * devices are in a single page above top of "normal" mem
  */
@@ -432,21 +452,23 @@ static int __init kvm_devices_init(void)
 	if (!MACHINE_IS_KVM)
 		return -ENODEV;
 
+	if (test_devices_support(real_memory_size) < 0)
+		return -ENODEV;
+
+	rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
+	if (rc)
+		return rc;
+
+	kvm_devices = (void *) real_memory_size;
+
 	kvm_root = root_device_register("kvm_s390");
 	if (IS_ERR(kvm_root)) {
 		rc = PTR_ERR(kvm_root);
 		printk(KERN_ERR "Could not register kvm_s390 root device");
+		vmem_remove_mapping(real_memory_size, PAGE_SIZE);
 		return rc;
 	}
 
-	rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
-	if (rc) {
-		root_device_unregister(kvm_root);
-		return rc;
-	}
-
-	kvm_devices = (void *) real_memory_size;
-
 	INIT_WORK(&hotplug_work, hotplug_devices);
 
 	service_subclass_irq_register();
diff -druNp linux-libre-3.8-gnu1/drivers/scsi/dc395x.c linux-libre-3.8.13-gnu1/drivers/scsi/dc395x.c
--- linux-libre-3.8-gnu1/drivers/scsi/dc395x.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/scsi/dc395x.c	2013-05-11 16:57:46.000000000 -0400
@@ -3747,13 +3747,13 @@ static struct DeviceCtlBlk *device_alloc
 	dcb->max_command = 1;
 	dcb->target_id = target;
 	dcb->target_lun = lun;
+	dcb->dev_mode = eeprom->target[target].cfg0;
 #ifndef DC395x_NO_DISCONNECT
 	dcb->identify_msg =
 	    IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun);
 #else
 	dcb->identify_msg = IDENTIFY(0, lun);
 #endif
-	dcb->dev_mode = eeprom->target[target].cfg0;
 	dcb->inquiry7 = 0;
 	dcb->sync_mode = 0;
 	dcb->min_nego_period = clock_period[period_index];
diff -druNp linux-libre-3.8-gnu1/drivers/scsi/libsas/sas_expander.c linux-libre-3.8.13-gnu1/drivers/scsi/libsas/sas_expander.c
--- linux-libre-3.8-gnu1/drivers/scsi/libsas/sas_expander.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/scsi/libsas/sas_expander.c	2013-05-11 16:57:46.000000000 -0400
@@ -235,6 +235,17 @@ static void sas_set_ex_phy(struct domain
 	linkrate  = phy->linkrate;
 	memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
 
+	/* Handle vacant phy - rest of dr data is not valid so skip it */
+	if (phy->phy_state == PHY_VACANT) {
+		memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+		phy->attached_dev_type = NO_DEVICE;
+		if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
+			phy->phy_id = phy_id;
+			goto skip;
+		} else
+			goto out;
+	}
+
 	phy->attached_dev_type = to_dev_type(dr);
 	if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
 		goto out;
@@ -272,6 +283,7 @@ static void sas_set_ex_phy(struct domain
 	phy->phy->maximum_linkrate = dr->pmax_linkrate;
 	phy->phy->negotiated_linkrate = phy->linkrate;
 
+ skip:
 	if (new_phy)
 		if (sas_phy_add(phy->phy)) {
 			sas_phy_free(phy->phy);
diff -druNp linux-libre-3.8-gnu1/drivers/scsi/storvsc_drv.c linux-libre-3.8.13-gnu1/drivers/scsi/storvsc_drv.c
--- linux-libre-3.8-gnu1/drivers/scsi/storvsc_drv.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/scsi/storvsc_drv.c	2013-05-11 16:57:46.000000000 -0400
@@ -467,6 +467,7 @@ static struct scatterlist *create_bounce
 	if (!bounce_sgl)
 		return NULL;
 
+	sg_init_table(bounce_sgl, num_pages);
 	for (i = 0; i < num_pages; i++) {
 		page_buf = alloc_page(GFP_ATOMIC);
 		if (!page_buf)
diff -druNp linux-libre-3.8-gnu1/drivers/spi/spi-mpc512x-psc.c linux-libre-3.8.13-gnu1/drivers/spi/spi-mpc512x-psc.c
--- linux-libre-3.8-gnu1/drivers/spi/spi-mpc512x-psc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/spi/spi-mpc512x-psc.c	2013-05-11 16:57:46.000000000 -0400
@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx
 
 		for (i = count; i > 0; i--) {
 			data = tx_buf ? *tx_buf++ : 0;
-			if (len == EOFBYTE)
+			if (len == EOFBYTE && t->cs_change)
 				setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
 			out_8(&fifo->txdata_8, data);
 			len--;
diff -druNp linux-libre-3.8-gnu1/drivers/spi/spi-s3c64xx.c linux-libre-3.8.13-gnu1/drivers/spi/spi-s3c64xx.c
--- linux-libre-3.8-gnu1/drivers/spi/spi-s3c64xx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/spi/spi-s3c64xx.c	2013-05-11 16:57:46.000000000 -0400
@@ -997,25 +997,30 @@ static irqreturn_t s3c64xx_spi_irq(int i
 {
 	struct s3c64xx_spi_driver_data *sdd = data;
 	struct spi_master *spi = sdd->master;
-	unsigned int val;
-
-	val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
-	val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
-		S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
-		S3C64XX_SPI_PND_TX_OVERRUN_CLR |
-		S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+	unsigned int val, clr = 0;
 
-	writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+	val = readl(sdd->regs + S3C64XX_SPI_STATUS);
 
-	if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
+	if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) {
+		clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR;
 		dev_err(&spi->dev, "RX overrun\n");
-	if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
+	}
+	if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) {
+		clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR;
 		dev_err(&spi->dev, "RX underrun\n");
-	if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
+	}
+	if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) {
+		clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR;
 		dev_err(&spi->dev, "TX overrun\n");
-	if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
+	}
+	if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) {
+		clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
 		dev_err(&spi->dev, "TX underrun\n");
+	}
+
+	/* Clear the pending irq by setting and then clearing it */
+	writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+	writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
 
 	return IRQ_HANDLED;
 }
@@ -1039,9 +1044,13 @@ static void s3c64xx_spi_hwinit(struct s3
 	writel(0, regs + S3C64XX_SPI_MODE_CFG);
 	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
 
-	/* Clear any irq pending bits */
-	writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
-				regs + S3C64XX_SPI_PENDING_CLR);
+	/* Clear any irq pending bits, should set and clear the bits */
+	val = S3C64XX_SPI_PND_RX_OVERRUN_CLR |
+		S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
+		S3C64XX_SPI_PND_TX_OVERRUN_CLR |
+		S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+	writel(val, regs + S3C64XX_SPI_PENDING_CLR);
+	writel(0, regs + S3C64XX_SPI_PENDING_CLR);
 
 	writel(0, regs + S3C64XX_SPI_SWAP_CFG);
 
diff -druNp linux-libre-3.8-gnu1/drivers/ssb/driver_chipcommon_pmu.c linux-libre-3.8.13-gnu1/drivers/ssb/driver_chipcommon_pmu.c
--- linux-libre-3.8-gnu1/drivers/ssb/driver_chipcommon_pmu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/ssb/driver_chipcommon_pmu.c	2013-05-11 16:57:46.000000000 -0400
@@ -675,3 +675,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_
 		return 0;
 	}
 }
+
+void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
+{
+	u32 pmu_ctl = 0;
+
+	switch (cc->dev->bus->chip_id) {
+	case 0x4322:
+		ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
+		ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
+		ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
+		if (spuravoid == 1)
+			ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
+		else
+			ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
+		pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
+		break;
+	case 43222:
+		/* TODO: BCM43222 requires updating PLLs too */
+		return;
+	default:
+		ssb_printk(KERN_ERR PFX
+			   "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
+			   cc->dev->bus->chip_id);
+		return;
+	}
+
+	chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
+}
+EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);
diff -druNp linux-libre-3.8-gnu1/drivers/staging/comedi/comedi_fops.c linux-libre-3.8.13-gnu1/drivers/staging/comedi/comedi_fops.c
--- linux-libre-3.8-gnu1/drivers/staging/comedi/comedi_fops.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/comedi/comedi_fops.c	2013-05-11 16:57:46.000000000 -0400
@@ -1547,6 +1547,11 @@ static long comedi_unlocked_ioctl(struct
 	/* Device config is special, because it must work on
 	 * an unconfigured device. */
 	if (cmd == COMEDI_DEVCONFIG) {
+		if (minor >= COMEDI_NUM_BOARD_MINORS) {
+			/* Device config not appropriate on non-board minors. */
+			rc = -ENOTTY;
+			goto done;
+		}
 		rc = do_devconfig_ioctl(dev,
 					(struct comedi_devconfig __user *)arg);
 		if (rc == 0)
@@ -1774,7 +1779,7 @@ static unsigned int comedi_poll(struct f
 
 	mask = 0;
 	read_subdev = comedi_get_read_subdevice(dev_file_info);
-	if (read_subdev) {
+	if (read_subdev && read_subdev->async) {
 		poll_wait(file, &read_subdev->async->wait_head, wait);
 		if (!read_subdev->busy
 		    || comedi_buf_read_n_available(read_subdev->async) > 0
@@ -1784,7 +1789,7 @@ static unsigned int comedi_poll(struct f
 		}
 	}
 	write_subdev = comedi_get_write_subdevice(dev_file_info);
-	if (write_subdev) {
+	if (write_subdev && write_subdev->async) {
 		poll_wait(file, &write_subdev->async->wait_head, wait);
 		comedi_buf_write_alloc(write_subdev->async,
 				       write_subdev->async->prealloc_bufsz);
@@ -1826,7 +1831,7 @@ static ssize_t comedi_write(struct file
 	}
 
 	s = comedi_get_write_subdevice(dev_file_info);
-	if (s == NULL) {
+	if (s == NULL || s->async == NULL) {
 		retval = -EIO;
 		goto done;
 	}
@@ -1937,7 +1942,7 @@ static ssize_t comedi_read(struct file *
 	}
 
 	s = comedi_get_read_subdevice(dev_file_info);
-	if (s == NULL) {
+	if (s == NULL || s->async == NULL) {
 		retval = -EIO;
 		goto done;
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/staging/comedi/drivers/dt9812.c linux-libre-3.8.13-gnu1/drivers/staging/comedi/drivers/dt9812.c
--- linux-libre-3.8-gnu1/drivers/staging/comedi/drivers/dt9812.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/comedi/drivers/dt9812.c	2013-05-11 16:57:46.000000000 -0400
@@ -948,12 +948,13 @@ static int dt9812_di_rinsn(struct comedi
 			   unsigned int *data)
 {
 	struct comedi_dt9812 *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
 	int n;
 	u8 bits = 0;
 
 	dt9812_digital_in(devpriv->slot, &bits);
 	for (n = 0; n < insn->n; n++)
-		data[n] = ((1 << insn->chanspec) & bits) != 0;
+		data[n] = ((1 << channel) & bits) != 0;
 	return n;
 }
 
@@ -962,12 +963,13 @@ static int dt9812_do_winsn(struct comedi
 			   unsigned int *data)
 {
 	struct comedi_dt9812 *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
 	int n;
 	u8 bits = 0;
 
 	dt9812_digital_out_shadow(devpriv->slot, &bits);
 	for (n = 0; n < insn->n; n++) {
-		u8 mask = 1 << insn->chanspec;
+		u8 mask = 1 << channel;
 
 		bits &= ~mask;
 		if (data[n])
@@ -982,13 +984,13 @@ static int dt9812_ai_rinsn(struct comedi
 			   unsigned int *data)
 {
 	struct comedi_dt9812 *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
 	int n;
 
 	for (n = 0; n < insn->n; n++) {
 		u16 value = 0;
 
-		dt9812_analog_in(devpriv->slot, insn->chanspec, &value,
-				 DT9812_GAIN_1);
+		dt9812_analog_in(devpriv->slot, channel, &value, DT9812_GAIN_1);
 		data[n] = value;
 	}
 	return n;
@@ -999,12 +1001,13 @@ static int dt9812_ao_rinsn(struct comedi
 			   unsigned int *data)
 {
 	struct comedi_dt9812 *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
 	int n;
 	u16 value;
 
 	for (n = 0; n < insn->n; n++) {
 		value = 0;
-		dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value);
+		dt9812_analog_out_shadow(devpriv->slot, channel, &value);
 		data[n] = value;
 	}
 	return n;
@@ -1015,10 +1018,11 @@ static int dt9812_ao_winsn(struct comedi
 			   unsigned int *data)
 {
 	struct comedi_dt9812 *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
 	int n;
 
 	for (n = 0; n < insn->n; n++)
-		dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]);
+		dt9812_analog_out(devpriv->slot, channel, data[n]);
 	return n;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/staging/comedi/drivers/ni_labpc.c linux-libre-3.8.13-gnu1/drivers/staging/comedi/drivers/ni_labpc.c
--- linux-libre-3.8-gnu1/drivers/staging/comedi/drivers/ni_labpc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/comedi/drivers/ni_labpc.c	2013-05-11 16:57:46.000000000 -0400
@@ -1202,7 +1202,8 @@ static int labpc_ai_cmd(struct comedi_de
 	else
 		channel = CR_CHAN(cmd->chanlist[0]);
 	/* munge channel bits for differential / scan disabled mode */
-	if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF)
+	if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
+	    aref == AREF_DIFF)
 		channel *= 2;
 	devpriv->command1_bits |= ADC_CHAN_BITS(channel);
 	devpriv->command1_bits |= thisboard->ai_range_code[range];
@@ -1217,21 +1218,6 @@ static int labpc_ai_cmd(struct comedi_de
 		devpriv->write_byte(devpriv->command1_bits,
 				    dev->iobase + COMMAND1_REG);
 	}
-	/*  setup any external triggering/pacing (command4 register) */
-	devpriv->command4_bits = 0;
-	if (cmd->convert_src != TRIG_EXT)
-		devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
-	/* XXX should discard first scan when using interval scanning
-	 * since manual says it is not synced with scan clock */
-	if (labpc_use_continuous_mode(cmd, mode) == 0) {
-		devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
-		if (cmd->scan_begin_src == TRIG_EXT)
-			devpriv->command4_bits |= EXT_SCAN_EN_BIT;
-	}
-	/*  single-ended/differential */
-	if (aref == AREF_DIFF)
-		devpriv->command4_bits |= ADC_DIFF_BIT;
-	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
 
 	devpriv->write_byte(cmd->chanlist_len,
 			    dev->iobase + INTERVAL_COUNT_REG);
@@ -1311,6 +1297,22 @@ static int labpc_ai_cmd(struct comedi_de
 		devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT;
 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
 
+	/*  setup any external triggering/pacing (command4 register) */
+	devpriv->command4_bits = 0;
+	if (cmd->convert_src != TRIG_EXT)
+		devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
+	/* XXX should discard first scan when using interval scanning
+	 * since manual says it is not synced with scan clock */
+	if (labpc_use_continuous_mode(cmd, mode) == 0) {
+		devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
+		if (cmd->scan_begin_src == TRIG_EXT)
+			devpriv->command4_bits |= EXT_SCAN_EN_BIT;
+	}
+	/*  single-ended/differential */
+	if (aref == AREF_DIFF)
+		devpriv->command4_bits |= ADC_DIFF_BIT;
+	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
+
 	/*  startup acquisition */
 
 	/*  command2 reg */
diff -druNp linux-libre-3.8-gnu1/drivers/staging/comedi/drivers/s626.c linux-libre-3.8.13-gnu1/drivers/staging/comedi/drivers/s626.c
--- linux-libre-3.8-gnu1/drivers/staging/comedi/drivers/s626.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/comedi/drivers/s626.c	2013-05-11 16:57:46.000000000 -0400
@@ -1482,7 +1482,7 @@ static int s626_ai_cmd(struct comedi_dev
 	case TRIG_NONE:
 		/*  continous acquisition */
 		devpriv->ai_continous = 1;
-		devpriv->ai_sample_count = 0;
+		devpriv->ai_sample_count = 1;
 		break;
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/staging/vt6656/dpc.c linux-libre-3.8.13-gnu1/drivers/staging/vt6656/dpc.c
--- linux-libre-3.8-gnu1/drivers/staging/vt6656/dpc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/vt6656/dpc.c	2013-05-11 16:57:46.000000000 -0400
@@ -1190,7 +1190,7 @@ static BOOL s_bHandleRxEncryption (
     if (byDecMode == KEY_CTL_WEP) {
         // handle WEP
         if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
-		(((PSKeyTable)(&pKey->pvKeyTable))->bSoftWEP == TRUE)) {
+		(((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == TRUE)) {
             // Software WEP
             // 1. 3253A
             // 2. WEP 256
@@ -1299,7 +1299,7 @@ static BOOL s_bHostWepRxEncryption (
         // handle WEP
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP\n");
         if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
-		(((PSKeyTable)(&pKey->pvKeyTable))->bSoftWEP == TRUE) ||
+		(((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == TRUE) ||
             (bOnFly == FALSE)) {
             // Software WEP
             // 1. 3253A
diff -druNp linux-libre-3.8-gnu1/drivers/staging/vt6656/main_usb.c linux-libre-3.8.13-gnu1/drivers/staging/vt6656/main_usb.c
--- linux-libre-3.8-gnu1/drivers/staging/vt6656/main_usb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/vt6656/main_usb.c	2013-05-11 16:57:46.000000000 -0400
@@ -644,8 +644,6 @@ static int vt6656_suspend(struct usb_int
 	if (device->flags & DEVICE_FLAGS_OPENED)
 		device_close(device->dev);
 
-	usb_put_dev(interface_to_usbdev(intf));
-
 	return 0;
 }
 
@@ -656,8 +654,6 @@ static int vt6656_resume(struct usb_inte
 	if (!device || !device->dev)
 		return -ENODEV;
 
-	usb_get_dev(interface_to_usbdev(intf));
-
 	if (!(device->flags & DEVICE_FLAGS_OPENED))
 		device_open(device->dev);
 
diff -druNp linux-libre-3.8-gnu1/drivers/staging/vt6656/rxtx.c linux-libre-3.8.13-gnu1/drivers/staging/vt6656/rxtx.c
--- linux-libre-3.8-gnu1/drivers/staging/vt6656/rxtx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/vt6656/rxtx.c	2013-05-11 16:57:46.000000000 -0400
@@ -1454,7 +1454,7 @@ s_bPacketToWirelessUsb(
 
     pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
 	if (bNeedEncryption && pTransmitKey->pvKeyTable) {
-		if (((PSKeyTable)&pTransmitKey->pvKeyTable)->bSoftWEP == TRUE)
+		if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == TRUE)
 			bSoftWEP = TRUE; /* WEP 256 */
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/staging/vt6656/usbpipe.c linux-libre-3.8.13-gnu1/drivers/staging/vt6656/usbpipe.c
--- linux-libre-3.8-gnu1/drivers/staging/vt6656/usbpipe.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/vt6656/usbpipe.c	2013-05-11 16:57:46.000000000 -0400
@@ -165,6 +165,11 @@ int PIPEnsControlOut(
     if (pDevice->Flags & fMP_CONTROL_WRITES)
         return STATUS_FAILURE;
 
+	if (pDevice->Flags & fMP_CONTROL_READS)
+		return STATUS_FAILURE;
+
+	MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
+
 	pDevice->sUsbCtlRequest.bRequestType = 0x40;
 	pDevice->sUsbCtlRequest.bRequest = byRequest;
 	pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
@@ -179,12 +184,13 @@ int PIPEnsControlOut(
 
 	ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
 	if (ntStatus != 0) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"control send request submission failed: %d\n",
+				ntStatus);
+		MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
 		return STATUS_FAILURE;
 	}
-	else {
-	    MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
-	}
+
 	spin_unlock_irq(&pDevice->lock);
     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
 
@@ -224,6 +230,11 @@ int PIPEnsControlIn(
     if (pDevice->Flags & fMP_CONTROL_READS)
 	return STATUS_FAILURE;
 
+	if (pDevice->Flags & fMP_CONTROL_WRITES)
+		return STATUS_FAILURE;
+
+	MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
+
 	pDevice->sUsbCtlRequest.bRequestType = 0xC0;
 	pDevice->sUsbCtlRequest.bRequest = byRequest;
 	pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
@@ -237,10 +248,11 @@ int PIPEnsControlIn(
 
 	ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
 	if (ntStatus != 0) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus);
-	}else {
-		MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
-    }
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"control request submission failed: %d\n", ntStatus);
+		MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
+		return STATUS_FAILURE;
+	}
 
 	spin_unlock_irq(&pDevice->lock);
     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
diff -druNp linux-libre-3.8-gnu1/drivers/staging/zram/zram_drv.c linux-libre-3.8.13-gnu1/drivers/staging/zram/zram_drv.c
--- linux-libre-3.8-gnu1/drivers/staging/zram/zram_drv.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/zram/zram_drv.c	2013-05-11 16:57:46.000000000 -0400
@@ -228,11 +228,12 @@ static int zram_bvec_read(struct zram *z
 		return 0;
 	}
 
-	user_mem = kmap_atomic(page);
 	if (is_partial_io(bvec))
 		/* Use  a temporary buffer to decompress the page */
-		uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	else
+		uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+
+	user_mem = kmap_atomic(page);
+	if (!is_partial_io(bvec))
 		uncmem = user_mem;
 
 	if (!uncmem) {
@@ -279,7 +280,7 @@ static int zram_bvec_write(struct zram *
 		 * This is a partial IO. We need to read the full page
 		 * before to write the changes.
 		 */
-		uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
 		if (!uncmem) {
 			pr_info("Error allocating temp memory!\n");
 			ret = -ENOMEM;
diff -druNp linux-libre-3.8-gnu1/drivers/staging/zsmalloc/Kconfig linux-libre-3.8.13-gnu1/drivers/staging/zsmalloc/Kconfig
--- linux-libre-3.8-gnu1/drivers/staging/zsmalloc/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/zsmalloc/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -1,5 +1,5 @@
 config ZSMALLOC
-	tristate "Memory allocator for compressed pages"
+	bool "Memory allocator for compressed pages"
 	default n
 	help
 	  zsmalloc is a slab-based memory allocator designed to store
diff -druNp linux-libre-3.8-gnu1/drivers/staging/zsmalloc/zsmalloc-main.c linux-libre-3.8.13-gnu1/drivers/staging/zsmalloc/zsmalloc-main.c
--- linux-libre-3.8-gnu1/drivers/staging/zsmalloc/zsmalloc-main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/staging/zsmalloc/zsmalloc-main.c	2013-05-11 16:57:46.000000000 -0400
@@ -222,11 +222,9 @@ struct zs_pool {
 /*
  * By default, zsmalloc uses a copy-based object mapping method to access
  * allocations that span two pages. However, if a particular architecture
- * 1) Implements local_flush_tlb_kernel_range() and 2) Performs VM mapping
- * faster than copying, then it should be added here so that
- * USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use page table
- * mapping rather than copying
- * for object mapping.
+ * performs VM mapping faster than copying, then it should be added here
+ * so that USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use
+ * page table mapping rather than copying for object mapping.
 */
 #if defined(CONFIG_ARM)
 #define USE_PGTABLE_MAPPING
@@ -659,11 +657,8 @@ static inline void __zs_unmap_object(str
 				struct page *pages[2], int off, int size)
 {
 	unsigned long addr = (unsigned long)area->vm_addr;
-	unsigned long end = addr + (PAGE_SIZE * 2);
 
-	flush_cache_vunmap(addr, end);
-	unmap_kernel_range_noflush(addr, PAGE_SIZE * 2);
-	local_flush_tlb_kernel_range(addr, end);
+	unmap_kernel_range(addr, PAGE_SIZE * 2);
 }
 
 #else /* USE_PGTABLE_MAPPING */
diff -druNp linux-libre-3.8-gnu1/drivers/target/iscsi/iscsi_target_auth.c linux-libre-3.8.13-gnu1/drivers/target/iscsi/iscsi_target_auth.c
--- linux-libre-3.8-gnu1/drivers/target/iscsi/iscsi_target_auth.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/iscsi/iscsi_target_auth.c	2013-05-11 16:57:46.000000000 -0400
@@ -166,6 +166,7 @@ static int chap_server_compute_md5(
 {
 	char *endptr;
 	unsigned long id;
+	unsigned char id_as_uchar;
 	unsigned char digest[MD5_SIGNATURE_SIZE];
 	unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2];
 	unsigned char identifier[10], *challenge = NULL;
@@ -355,7 +356,9 @@ static int chap_server_compute_md5(
 		goto out;
 	}
 
-	sg_init_one(&sg, &id, 1);
+	/* To handle both endiannesses */
+	id_as_uchar = id;
+	sg_init_one(&sg, &id_as_uchar, 1);
 	ret = crypto_hash_update(&desc, &sg, 1);
 	if (ret < 0) {
 		pr_err("crypto_hash_update() failed for id\n");
diff -druNp linux-libre-3.8-gnu1/drivers/target/iscsi/iscsi_target.c linux-libre-3.8.13-gnu1/drivers/target/iscsi/iscsi_target.c
--- linux-libre-3.8-gnu1/drivers/target/iscsi/iscsi_target.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/iscsi/iscsi_target.c	2013-05-11 16:57:46.000000000 -0400
@@ -3570,6 +3570,10 @@ check_rsp_state:
 				spin_lock_bh(&cmd->istate_lock);
 				cmd->i_state = ISTATE_SENT_STATUS;
 				spin_unlock_bh(&cmd->istate_lock);
+
+				if (atomic_read(&conn->check_immediate_queue))
+					return 1;
+
 				continue;
 			} else if (ret == 2) {
 				/* Still must send status,
@@ -3659,7 +3663,7 @@ check_rsp_state:
 		}
 
 		if (atomic_read(&conn->check_immediate_queue))
-			break;
+			return 1;
 	}
 
 	return 0;
@@ -3703,12 +3707,15 @@ restart:
 		     signal_pending(current))
 			goto transport_err;
 
+get_immediate:
 		ret = handle_immediate_queue(conn);
 		if (ret < 0)
 			goto transport_err;
 
 		ret = handle_response_queue(conn);
-		if (ret == -EAGAIN)
+		if (ret == 1)
+			goto get_immediate;
+		else if (ret == -EAGAIN)
 			goto restart;
 		else if (ret < 0)
 			goto transport_err;
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_alua.c linux-libre-3.8.13-gnu1/drivers/target/target_core_alua.c
--- linux-libre-3.8-gnu1/drivers/target/target_core_alua.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_alua.c	2013-05-11 16:57:46.000000000 -0400
@@ -408,6 +408,7 @@ static inline int core_alua_state_standb
 	case REPORT_LUNS:
 	case RECEIVE_DIAGNOSTIC:
 	case SEND_DIAGNOSTIC:
+		return 0;
 	case MAINTENANCE_IN:
 		switch (cdb[1] & 0x1f) {
 		case MI_REPORT_TARGET_PGS:
@@ -450,6 +451,7 @@ static inline int core_alua_state_unavai
 	switch (cdb[0]) {
 	case INQUIRY:
 	case REPORT_LUNS:
+		return 0;
 	case MAINTENANCE_IN:
 		switch (cdb[1] & 0x1f) {
 		case MI_REPORT_TARGET_PGS:
@@ -490,6 +492,7 @@ static inline int core_alua_state_transi
 	switch (cdb[0]) {
 	case INQUIRY:
 	case REPORT_LUNS:
+		return 0;
 	case MAINTENANCE_IN:
 		switch (cdb[1] & 0x1f) {
 		case MI_REPORT_TARGET_PGS:
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_device.c linux-libre-3.8.13-gnu1/drivers/target/target_core_device.c
--- linux-libre-3.8-gnu1/drivers/target/target_core_device.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_device.c	2013-05-11 16:57:46.000000000 -0400
@@ -1182,24 +1182,18 @@ static struct se_lun *core_dev_get_lun(s
 
 struct se_lun_acl *core_dev_init_initiator_node_lun_acl(
 	struct se_portal_group *tpg,
+	struct se_node_acl *nacl,
 	u32 mapped_lun,
-	char *initiatorname,
 	int *ret)
 {
 	struct se_lun_acl *lacl;
-	struct se_node_acl *nacl;
 
-	if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) {
+	if (strlen(nacl->initiatorname) >= TRANSPORT_IQN_LEN) {
 		pr_err("%s InitiatorName exceeds maximum size.\n",
 			tpg->se_tpg_tfo->get_fabric_name());
 		*ret = -EOVERFLOW;
 		return NULL;
 	}
-	nacl = core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if (!nacl) {
-		*ret = -EINVAL;
-		return NULL;
-	}
 	lacl = kzalloc(sizeof(struct se_lun_acl), GFP_KERNEL);
 	if (!lacl) {
 		pr_err("Unable to allocate memory for struct se_lun_acl.\n");
@@ -1210,7 +1204,8 @@ struct se_lun_acl *core_dev_init_initiat
 	INIT_LIST_HEAD(&lacl->lacl_list);
 	lacl->mapped_lun = mapped_lun;
 	lacl->se_lun_nacl = nacl;
-	snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
+	snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s",
+		 nacl->initiatorname);
 
 	return lacl;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_fabric_configfs.c linux-libre-3.8.13-gnu1/drivers/target/target_core_fabric_configfs.c
--- linux-libre-3.8-gnu1/drivers/target/target_core_fabric_configfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_fabric_configfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -354,9 +354,17 @@ static struct config_group *target_fabri
 		ret = -EINVAL;
 		goto out;
 	}
+	if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
+		pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG"
+			"-1: %u for Target Portal Group: %u\n", mapped_lun,
+			TRANSPORT_MAX_LUNS_PER_TPG-1,
+			se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
+		ret = -EINVAL;
+		goto out;
+	}
 
-	lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
-			config_item_name(acl_ci), &ret);
+	lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl,
+			mapped_lun, &ret);
 	if (!lacl) {
 		ret = -EINVAL;
 		goto out;
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_file.h linux-libre-3.8.13-gnu1/drivers/target/target_core_file.h
--- linux-libre-3.8-gnu1/drivers/target/target_core_file.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_file.h	2013-05-11 16:57:46.000000000 -0400
@@ -7,7 +7,7 @@
 #define FD_DEVICE_QUEUE_DEPTH	32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE		512
-#define FD_MAX_SECTORS		1024
+#define FD_MAX_SECTORS		2048
 
 #define RRF_EMULATE_CDB		0x01
 #define RRF_GOT_LBA		0x02
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_internal.h linux-libre-3.8.13-gnu1/drivers/target/target_core_internal.h
--- linux-libre-3.8-gnu1/drivers/target/target_core_internal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_internal.h	2013-05-11 16:57:46.000000000 -0400
@@ -45,7 +45,7 @@ struct se_lun *core_dev_add_lun(struct s
 int	core_dev_del_lun(struct se_portal_group *, u32);
 struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
 struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
-		u32, char *, int *);
+		struct se_node_acl *, u32, int *);
 int	core_dev_add_initiator_node_lun_acl(struct se_portal_group *,
 		struct se_lun_acl *, u32, u32);
 int	core_dev_del_initiator_node_lun_acl(struct se_portal_group *,
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_pscsi.c linux-libre-3.8.13-gnu1/drivers/target/target_core_pscsi.c
--- linux-libre-3.8-gnu1/drivers/target/target_core_pscsi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_pscsi.c	2013-05-11 16:57:46.000000000 -0400
@@ -940,7 +940,6 @@ pscsi_map_sg(struct se_cmd *cmd, struct
 				bio = NULL;
 			}
 
-			page++;
 			len -= bytes;
 			data_len -= bytes;
 			off = 0;
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_tpg.c linux-libre-3.8.13-gnu1/drivers/target/target_core_tpg.c
--- linux-libre-3.8-gnu1/drivers/target/target_core_tpg.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_tpg.c	2013-05-11 16:57:46.000000000 -0400
@@ -111,16 +111,10 @@ struct se_node_acl *core_tpg_get_initiat
 	struct se_node_acl *acl;
 
 	spin_lock_irq(&tpg->acl_node_lock);
-	list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
-		if (!strcmp(acl->initiatorname, initiatorname) &&
-		    !acl->dynamic_node_acl) {
-			spin_unlock_irq(&tpg->acl_node_lock);
-			return acl;
-		}
-	}
+	acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
 	spin_unlock_irq(&tpg->acl_node_lock);
 
-	return NULL;
+	return acl;
 }
 
 /*	core_tpg_add_node_to_devs():
diff -druNp linux-libre-3.8-gnu1/drivers/target/target_core_transport.c linux-libre-3.8.13-gnu1/drivers/target/target_core_transport.c
--- linux-libre-3.8-gnu1/drivers/target/target_core_transport.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/target/target_core_transport.c	2013-05-11 16:57:46.000000000 -0400
@@ -1136,8 +1136,10 @@ target_setup_cmd_from_cdb(struct se_cmd
 		return ret;
 
 	ret = target_check_reservation(cmd);
-	if (ret)
+	if (ret) {
+		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
 		return ret;
+	}
 
 	ret = dev->transport->parse_cdb(cmd);
 	if (ret)
diff -druNp linux-libre-3.8-gnu1/drivers/thermal/thermal_sys.c linux-libre-3.8.13-gnu1/drivers/thermal/thermal_sys.c
--- linux-libre-3.8-gnu1/drivers/thermal/thermal_sys.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/thermal/thermal_sys.c	2013-05-11 16:57:46.000000000 -0400
@@ -1807,6 +1807,7 @@ static int __init thermal_init(void)
 		idr_destroy(&thermal_cdev_idr);
 		mutex_destroy(&thermal_idr_lock);
 		mutex_destroy(&thermal_list_lock);
+		return result;
 	}
 	result = genetlink_init();
 	return result;
diff -druNp linux-libre-3.8-gnu1/drivers/tty/n_gsm.c linux-libre-3.8.13-gnu1/drivers/tty/n_gsm.c
--- linux-libre-3.8-gnu1/drivers/tty/n_gsm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/n_gsm.c	2013-05-11 16:57:46.000000000 -0400
@@ -1689,6 +1689,8 @@ static inline void dlci_put(struct gsm_d
 	tty_port_put(&dlci->port);
 }
 
+static void gsm_destroy_network(struct gsm_dlci *dlci);
+
 /**
  *	gsm_dlci_release		-	release DLCI
  *	@dlci: DLCI to destroy
@@ -1702,9 +1704,19 @@ static void gsm_dlci_release(struct gsm_
 {
 	struct tty_struct *tty = tty_port_tty_get(&dlci->port);
 	if (tty) {
+		mutex_lock(&dlci->mutex);
+		gsm_destroy_network(dlci);
+		mutex_unlock(&dlci->mutex);
+
+		/* tty_vhangup needs the tty_lock, so unlock and
+		   relock after doing the hangup. */
+		tty_unlock(tty);
 		tty_vhangup(tty);
+		tty_lock(tty);
+		tty_port_tty_set(&dlci->port, NULL);
 		tty_kref_put(tty);
 	}
+	dlci->state = DLCI_CLOSED;
 	dlci_put(dlci);
 }
 
@@ -2947,6 +2959,8 @@ static void gsmtty_close(struct tty_stru
 
 	if (dlci == NULL)
 		return;
+	if (dlci->state == DLCI_CLOSED)
+		return;
 	mutex_lock(&dlci->mutex);
 	gsm_destroy_network(dlci);
 	mutex_unlock(&dlci->mutex);
@@ -2965,6 +2979,8 @@ out:
 static void gsmtty_hangup(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return;
 	tty_port_hangup(&dlci->port);
 	gsm_dlci_begin_close(dlci);
 }
@@ -2972,9 +2988,12 @@ static void gsmtty_hangup(struct tty_str
 static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf,
 								    int len)
 {
+	int sent;
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 	/* Stuff the bytes into the fifo queue */
-	int sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock);
+	sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock);
 	/* Need to kick the channel */
 	gsm_dlci_data_kick(dlci);
 	return sent;
@@ -2983,18 +3002,24 @@ static int gsmtty_write(struct tty_struc
 static int gsmtty_write_room(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 	return TX_SIZE - kfifo_len(dlci->fifo);
 }
 
 static int gsmtty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 	return kfifo_len(dlci->fifo);
 }
 
 static void gsmtty_flush_buffer(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return;
 	/* Caution needed: If we implement reliable transport classes
 	   then the data being transmitted can't simply be junked once
 	   it has first hit the stack. Until then we can just blow it
@@ -3013,6 +3038,8 @@ static void gsmtty_wait_until_sent(struc
 static int gsmtty_tiocmget(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 	return dlci->modem_rx;
 }
 
@@ -3022,6 +3049,8 @@ static int gsmtty_tiocmset(struct tty_st
 	struct gsm_dlci *dlci = tty->driver_data;
 	unsigned int modem_tx = dlci->modem_tx;
 
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 	modem_tx &= ~clear;
 	modem_tx |= set;
 
@@ -3040,6 +3069,8 @@ static int gsmtty_ioctl(struct tty_struc
 	struct gsm_netconfig nc;
 	int index;
 
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 	switch (cmd) {
 	case GSMIOC_ENABLE_NET:
 		if (copy_from_user(&nc, (void __user *)arg, sizeof(nc)))
@@ -3066,6 +3097,9 @@ static int gsmtty_ioctl(struct tty_struc
 
 static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
+	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return;
 	/* For the moment its fixed. In actual fact the speed information
 	   for the virtual channel can be propogated in both directions by
 	   the RPN control message. This however rapidly gets nasty as we
@@ -3077,6 +3111,8 @@ static void gsmtty_set_termios(struct tt
 static void gsmtty_throttle(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return;
 	if (tty->termios.c_cflag & CRTSCTS)
 		dlci->modem_tx &= ~TIOCM_DTR;
 	dlci->throttled = 1;
@@ -3087,6 +3123,8 @@ static void gsmtty_throttle(struct tty_s
 static void gsmtty_unthrottle(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	if (dlci->state == DLCI_CLOSED)
+		return;
 	if (tty->termios.c_cflag & CRTSCTS)
 		dlci->modem_tx |= TIOCM_DTR;
 	dlci->throttled = 0;
@@ -3098,6 +3136,8 @@ static int gsmtty_break_ctl(struct tty_s
 {
 	struct gsm_dlci *dlci = tty->driver_data;
 	int encode = 0;	/* Off */
+	if (dlci->state == DLCI_CLOSED)
+		return -EINVAL;
 
 	if (state == -1)	/* "On indefinitely" - we can't encode this
 				    properly */
diff -druNp linux-libre-3.8-gnu1/drivers/tty/pty.c linux-libre-3.8.13-gnu1/drivers/tty/pty.c
--- linux-libre-3.8-gnu1/drivers/tty/pty.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/pty.c	2013-05-11 16:57:46.000000000 -0400
@@ -47,7 +47,6 @@ static void pty_close(struct tty_struct
 	/* Review - krefs on tty_link ?? */
 	if (!tty->link)
 		return;
-	tty->link->packet = 0;
 	set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
 	wake_up_interruptible(&tty->link->read_wait);
 	wake_up_interruptible(&tty->link->write_wait);
@@ -676,6 +675,9 @@ static int ptmx_open(struct inode *inode
 
 	nonseekable_open(inode, filp);
 
+	/* We refuse fsnotify events on ptmx, since it's a shared resource */
+	filp->f_mode |= FMODE_NONOTIFY;
+
 	retval = tty_alloc_file(filp);
 	if (retval)
 		return retval;
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/8250/8250.c linux-libre-3.8.13-gnu1/drivers/tty/serial/8250/8250.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/8250/8250.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/8250/8250.c	2013-05-11 16:57:46.000000000 -0400
@@ -308,7 +308,28 @@ static const struct serial8250_config ua
 	},
 	[PORT_8250_CIR] = {
 		.name		= "CIR port"
-	}
+	},
+	[PORT_ALTR_16550_F32] = {
+		.name		= "Altera 16550 FIFO32",
+		.fifo_size	= 32,
+		.tx_loadsz	= 32,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
+	},
+	[PORT_ALTR_16550_F64] = {
+		.name		= "Altera 16550 FIFO64",
+		.fifo_size	= 64,
+		.tx_loadsz	= 64,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
+	},
+	[PORT_ALTR_16550_F128] = {
+		.name		= "Altera 16550 FIFO128",
+		.fifo_size	= 128,
+		.tx_loadsz	= 128,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
+	},
 };
 
 /* Uart divisor latch read */
@@ -3430,3 +3451,32 @@ module_param_array(probe_rsa, ulong, &pr
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
+
+#ifndef MODULE
+/* This module was renamed to 8250_core in 3.7.  Keep the old "8250" name
+ * working as well for the module options so we don't break people.  We
+ * need to keep the names identical and the convenient macros will happily
+ * refuse to let us do that by failing the build with redefinition errors
+ * of global variables.  So we stick them inside a dummy function to avoid
+ * those conflicts.  The options still get parsed, and the redefined
+ * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
+ *
+ * This is hacky.  I'm sorry.
+ */
+static void __used s8250_options(void)
+{
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "8250."
+
+	module_param_cb(share_irqs, &param_ops_uint, &share_irqs, 0644);
+	module_param_cb(nr_uarts, &param_ops_uint, &nr_uarts, 0644);
+	module_param_cb(skip_txen_test, &param_ops_uint, &skip_txen_test, 0644);
+#ifdef CONFIG_SERIAL_8250_RSA
+	__module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
+		&param_array_ops, .arr = &__param_arr_probe_rsa,
+		0444, -1);
+#endif
+}
+#else
+MODULE_ALIAS("8250");
+#endif
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/8250/8250_pci.c linux-libre-3.8.13-gnu1/drivers/tty/serial/8250/8250_pci.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/8250/8250_pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/8250/8250_pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -1321,6 +1321,7 @@ pci_wch_ch353_setup(struct serial_privat
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588	0x1588
 
 /*
  * Master list of serial port init/setup/exit quirks.
@@ -1592,15 +1593,6 @@ static struct pci_serial_quirk pci_seria
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_PLX,
-		.device		= PCI_DEVICE_ID_PLX_9050,
-		.subvendor	= PCI_VENDOR_ID_PLX,
-		.subdevice	= PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
-		.init		= pci_plx9050_init,
-		.setup		= pci_default_setup,
-		.exit		= pci_plx9050_exit,
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_PLX,
 		.device		= PCI_DEVICE_ID_PLX_ROMULUS,
 		.subvendor	= PCI_VENDOR_ID_PLX,
 		.subdevice	= PCI_DEVICE_ID_PLX_ROMULUS,
@@ -3456,7 +3448,12 @@ static struct pci_device_id serial_pci_t
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 		PCI_VENDOR_ID_PLX,
 		PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
-		pbn_b0_4_115200 },
+		pbn_b2_4_115200 },
+	/* Unknown card - subdevice 0x1588 */
+	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+		PCI_VENDOR_ID_PLX,
+		PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0,
+		pbn_b2_8_115200 },
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 		PCI_SUBVENDOR_ID_KEYSPAN,
 		PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
@@ -4449,6 +4446,10 @@ static struct pci_device_id serial_pci_t
 		PCI_VENDOR_ID_IBM, 0x0299,
 		0, 0, pbn_b0_bt_2_115200 },
 
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+		0x1000, 0x0012,
+		0, 0, pbn_b0_bt_2_115200 },
+
 	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
 		0xA000, 0x1000,
 		0, 0, pbn_b0_1_115200 },
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/atmel_serial.c linux-libre-3.8.13-gnu1/drivers/tty/serial/atmel_serial.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/atmel_serial.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/atmel_serial.c	2013-05-11 16:57:46.000000000 -0400
@@ -158,7 +158,7 @@ struct atmel_uart_port {
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
-static unsigned long atmel_ports_in_use;
+static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);
 
 #ifdef SUPPORT_SYSRQ
 static struct console atmel_console;
@@ -1768,15 +1768,14 @@ static int atmel_serial_probe(struct pla
 	if (ret < 0)
 		/* port id not found in platform data nor device-tree aliases:
 		 * auto-enumerate it */
-		ret = find_first_zero_bit(&atmel_ports_in_use,
-				sizeof(atmel_ports_in_use));
+		ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART);
 
-	if (ret > ATMEL_MAX_UART) {
+	if (ret >= ATMEL_MAX_UART) {
 		ret = -ENODEV;
 		goto err;
 	}
 
-	if (test_and_set_bit(ret, &atmel_ports_in_use)) {
+	if (test_and_set_bit(ret, atmel_ports_in_use)) {
 		/* port already in use */
 		ret = -EBUSY;
 		goto err;
@@ -1856,7 +1855,7 @@ static int atmel_serial_remove(struct pl
 
 	/* "port" is allocated statically, so we shouldn't free it */
 
-	clear_bit(port->line, &atmel_ports_in_use);
+	clear_bit(port->line, atmel_ports_in_use);
 
 	clk_put(atmel_port->clk);
 
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/imx.c linux-libre-3.8.13-gnu1/drivers/tty/serial/imx.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/imx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/imx.c	2013-05-11 16:57:46.000000000 -0400
@@ -1213,8 +1213,14 @@ imx_console_write(struct console *co, co
 	struct imx_port_ucrs old_ucr;
 	unsigned int ucr1;
 	unsigned long flags;
+	int locked = 1;
 
-	spin_lock_irqsave(&sport->port.lock, flags);
+	if (sport->port.sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock_irqsave(&sport->port.lock, flags);
+	else
+		spin_lock_irqsave(&sport->port.lock, flags);
 
 	/*
 	 *	First, save UCR1/2/3 and then disable interrupts
@@ -1241,7 +1247,8 @@ imx_console_write(struct console *co, co
 
 	imx_port_ucrs_restore(&sport->port, &old_ucr);
 
-	spin_unlock_irqrestore(&sport->port.lock, flags);
+	if (locked)
+		spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 /*
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/Kconfig linux-libre-3.8.13-gnu1/drivers/tty/serial/Kconfig
--- linux-libre-3.8-gnu1/drivers/tty/serial/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -209,14 +209,14 @@ config SERIAL_SAMSUNG
 config SERIAL_SAMSUNG_UARTS_4
 	bool
 	depends on PLAT_SAMSUNG
-	default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
+	default y if !(CPU_S3C2410 || CPU_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
 	help
 	  Internal node for the common case of 4 Samsung compatible UARTs
 
 config SERIAL_SAMSUNG_UARTS
 	int
 	depends on PLAT_SAMSUNG
-	default 6 if ARCH_S5P6450
+	default 6 if CPU_S5P6450
 	default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
 	default 3
 	help
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/of_serial.c linux-libre-3.8.13-gnu1/drivers/tty/serial/of_serial.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/of_serial.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/of_serial.c	2013-05-11 16:57:46.000000000 -0400
@@ -240,6 +240,12 @@ static struct of_device_id of_platform_s
 	{ .compatible = "ns16850",  .data = (void *)PORT_16850, },
 	{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
 	{ .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
+	{ .compatible = "altr,16550-FIFO32",
+		.data = (void *)PORT_ALTR_16550_F32, },
+	{ .compatible = "altr,16550-FIFO64",
+		.data = (void *)PORT_ALTR_16550_F64, },
+	{ .compatible = "altr,16550-FIFO128",
+		.data = (void *)PORT_ALTR_16550_F128, },
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
 	{ .compatible = "ibm,qpace-nwp-serial",
 		.data = (void *)PORT_NWPSERIAL, },
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/serial_core.c linux-libre-3.8.13-gnu1/drivers/tty/serial/serial_core.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/serial_core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/serial_core.c	2013-05-11 16:57:46.000000000 -0400
@@ -1940,6 +1940,8 @@ int uart_suspend_port(struct uart_driver
 		mutex_unlock(&port->mutex);
 		return 0;
 	}
+	put_device(tty_dev);
+
 	if (console_suspend_enabled || !uart_console(uport))
 		uport->suspended = 1;
 
@@ -2005,9 +2007,11 @@ int uart_resume_port(struct uart_driver
 			disable_irq_wake(uport->irq);
 			uport->irq_wake = 0;
 		}
+		put_device(tty_dev);
 		mutex_unlock(&port->mutex);
 		return 0;
 	}
+	put_device(tty_dev);
 	uport->suspended = 0;
 
 	/*
diff -druNp linux-libre-3.8-gnu1/drivers/tty/serial/sunsu.c linux-libre-3.8.13-gnu1/drivers/tty/serial/sunsu.c
--- linux-libre-3.8-gnu1/drivers/tty/serial/sunsu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/serial/sunsu.c	2013-05-11 16:57:46.000000000 -0400
@@ -974,6 +974,7 @@ static struct uart_ops sunsu_pops = {
 #define UART_NR	4
 
 static struct uart_sunsu_port sunsu_ports[UART_NR];
+static int nr_inst; /* Number of already registered ports */
 
 #ifdef CONFIG_SERIO
 
@@ -1343,13 +1344,8 @@ static int __init sunsu_console_setup(st
 	printk("Console: ttyS%d (SU)\n",
 	       (sunsu_reg.minor - 64) + co->index);
 
-	/*
-	 * Check whether an invalid uart number has been specified, and
-	 * if so, search for the first available port that does have
-	 * console support.
-	 */
-	if (co->index >= UART_NR)
-		co->index = 0;
+	if (co->index > nr_inst)
+		return -ENODEV;
 	port = &sunsu_ports[co->index].port;
 
 	/*
@@ -1414,7 +1410,6 @@ static enum su_type su_get_type(struct d
 
 static int su_probe(struct platform_device *op)
 {
-	static int inst;
 	struct device_node *dp = op->dev.of_node;
 	struct uart_sunsu_port *up;
 	struct resource *rp;
@@ -1424,16 +1419,16 @@ static int su_probe(struct platform_devi
 
 	type = su_get_type(dp);
 	if (type == SU_PORT_PORT) {
-		if (inst >= UART_NR)
+		if (nr_inst >= UART_NR)
 			return -EINVAL;
-		up = &sunsu_ports[inst];
+		up = &sunsu_ports[nr_inst];
 	} else {
 		up = kzalloc(sizeof(*up), GFP_KERNEL);
 		if (!up)
 			return -ENOMEM;
 	}
 
-	up->port.line = inst;
+	up->port.line = nr_inst;
 
 	spin_lock_init(&up->port.lock);
 
@@ -1467,6 +1462,8 @@ static int su_probe(struct platform_devi
 		}
 		dev_set_drvdata(&op->dev, up);
 
+		nr_inst++;
+
 		return 0;
 	}
 
@@ -1494,7 +1491,7 @@ static int su_probe(struct platform_devi
 
 	dev_set_drvdata(&op->dev, up);
 
-	inst++;
+	nr_inst++;
 
 	return 0;
 
diff -druNp linux-libre-3.8-gnu1/drivers/tty/tty_buffer.c linux-libre-3.8.13-gnu1/drivers/tty/tty_buffer.c
--- linux-libre-3.8-gnu1/drivers/tty/tty_buffer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/tty_buffer.c	2013-05-11 16:57:46.000000000 -0400
@@ -473,7 +473,7 @@ static void flush_to_ldisc(struct work_s
 	struct tty_ldisc *disc;
 
 	tty = port->itty;
-	if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n"))
+	if (tty == NULL)
 		return;
 
 	disc = tty_ldisc_ref(tty);
diff -druNp linux-libre-3.8-gnu1/drivers/tty/tty_io.c linux-libre-3.8.13-gnu1/drivers/tty/tty_io.c
--- linux-libre-3.8-gnu1/drivers/tty/tty_io.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/tty_io.c	2013-05-11 16:57:46.000000000 -0400
@@ -941,6 +941,14 @@ void start_tty(struct tty_struct *tty)
 
 EXPORT_SYMBOL(start_tty);
 
+/* We limit tty time update visibility to every 8 seconds or so. */
+static void tty_update_time(struct timespec *time)
+{
+	unsigned long sec = get_seconds() & ~7;
+	if ((long)(sec - time->tv_sec) > 0)
+		time->tv_sec = sec;
+}
+
 /**
  *	tty_read	-	read method for tty device files
  *	@file: pointer to tty file
@@ -977,8 +985,10 @@ static ssize_t tty_read(struct file *fil
 	else
 		i = -EIO;
 	tty_ldisc_deref(ld);
+
 	if (i > 0)
-		inode->i_atime = current_fs_time(inode->i_sb);
+		tty_update_time(&inode->i_atime);
+
 	return i;
 }
 
@@ -1081,7 +1091,7 @@ static inline ssize_t do_tty_write(
 	}
 	if (written) {
 		struct inode *inode = file->f_path.dentry->d_inode;
-		inode->i_mtime = current_fs_time(inode->i_sb);
+		tty_update_time(&inode->i_mtime);
 		ret = written;
 	}
 out:
diff -druNp linux-libre-3.8-gnu1/drivers/tty/tty_ioctl.c linux-libre-3.8.13-gnu1/drivers/tty/tty_ioctl.c
--- linux-libre-3.8-gnu1/drivers/tty/tty_ioctl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/tty_ioctl.c	2013-05-11 16:57:46.000000000 -0400
@@ -617,7 +617,7 @@ static int set_termios(struct tty_struct
 	if (opt & TERMIOS_WAIT) {
 		tty_wait_until_sent(tty, 0);
 		if (signal_pending(current))
-			return -EINTR;
+			return -ERESTARTSYS;
 	}
 
 	tty_set_termios(tty, &tmp_termios);
@@ -684,7 +684,7 @@ static int set_termiox(struct tty_struct
 	if (opt & TERMIOS_WAIT) {
 		tty_wait_until_sent(tty, 0);
 		if (signal_pending(current))
-			return -EINTR;
+			return -ERESTARTSYS;
 	}
 
 	mutex_lock(&tty->termios_mutex);
diff -druNp linux-libre-3.8-gnu1/drivers/tty/tty_ldisc.c linux-libre-3.8.13-gnu1/drivers/tty/tty_ldisc.c
--- linux-libre-3.8-gnu1/drivers/tty/tty_ldisc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/tty_ldisc.c	2013-05-11 16:57:46.000000000 -0400
@@ -934,17 +934,17 @@ void tty_ldisc_release(struct tty_struct
 	 * race with the set_ldisc code path.
 	 */
 
-	tty_lock_pair(tty, o_tty);
 	tty_ldisc_halt(tty);
-	tty_ldisc_flush_works(tty);
-	if (o_tty) {
+	if (o_tty)
 		tty_ldisc_halt(o_tty);
+
+	tty_ldisc_flush_works(tty);
+	if (o_tty)
 		tty_ldisc_flush_works(o_tty);
-	}
 
+	tty_lock_pair(tty, o_tty);
 	/* This will need doing differently if we need to lock */
 	tty_ldisc_kill(tty);
-
 	if (o_tty)
 		tty_ldisc_kill(o_tty);
 
diff -druNp linux-libre-3.8-gnu1/drivers/tty/vt/vc_screen.c linux-libre-3.8.13-gnu1/drivers/tty/vt/vc_screen.c
--- linux-libre-3.8-gnu1/drivers/tty/vt/vc_screen.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/vt/vc_screen.c	2013-05-11 16:57:46.000000000 -0400
@@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data
 static struct vcs_poll_data *
 vcs_poll_data_get(struct file *file)
 {
-	struct vcs_poll_data *poll = file->private_data;
+	struct vcs_poll_data *poll = file->private_data, *kill = NULL;
 
 	if (poll)
 		return poll;
@@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file)
 		file->private_data = poll;
 	} else {
 		/* someone else raced ahead of us */
-		vcs_poll_data_free(poll);
+		kill = poll;
 		poll = file->private_data;
 	}
 	spin_unlock(&file->f_lock);
+	if (kill)
+		vcs_poll_data_free(kill);
 
 	return poll;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/tty/vt/vt.c linux-libre-3.8.13-gnu1/drivers/tty/vt/vt.c
--- linux-libre-3.8-gnu1/drivers/tty/vt/vt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/tty/vt/vt.c	2013-05-11 16:57:46.000000000 -0400
@@ -539,7 +539,7 @@ static void insert_char(struct vc_data *
 {
 	unsigned short *p = (unsigned short *) vc->vc_pos;
 
-	scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
+	scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
 	scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
 	vc->vc_need_wrap = 0;
 	if (DO_UPDATE(vc))
@@ -638,7 +638,7 @@ static inline void save_screen(struct vc
  *	Redrawing of screen
  */
 
-static void clear_buffer_attributes(struct vc_data *vc)
+void clear_buffer_attributes(struct vc_data *vc)
 {
 	unsigned short *p = (unsigned short *)vc->vc_origin;
 	int count = vc->vc_screenbuf_size / 2;
@@ -2987,7 +2987,7 @@ int __init vty_init(const struct file_op
 
 static struct class *vtconsole_class;
 
-static int bind_con_driver(const struct consw *csw, int first, int last,
+static int do_bind_con_driver(const struct consw *csw, int first, int last,
 			   int deflt)
 {
 	struct module *owner = csw->owner;
@@ -2998,7 +2998,7 @@ static int bind_con_driver(const struct
 	if (!try_module_get(owner))
 		return -ENODEV;
 
-	console_lock();
+	WARN_CONSOLE_UNLOCKED();
 
 	/* check if driver is registered */
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
@@ -3083,11 +3083,22 @@ static int bind_con_driver(const struct
 
 	retval = 0;
 err:
-	console_unlock();
 	module_put(owner);
 	return retval;
 };
 
+
+static int bind_con_driver(const struct consw *csw, int first, int last,
+			   int deflt)
+{
+	int ret;
+
+	console_lock();
+	ret = do_bind_con_driver(csw, first, last, deflt);
+	console_unlock();
+	return ret;
+}
+
 #ifdef CONFIG_VT_HW_CONSOLE_BINDING
 static int con_is_graphics(const struct consw *csw, int first, int last)
 {
@@ -3124,6 +3135,18 @@ static int con_is_graphics(const struct
  */
 int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 {
+	int retval;
+
+	console_lock();
+	retval = do_unbind_con_driver(csw, first, last, deflt);
+	console_unlock();
+	return retval;
+}
+EXPORT_SYMBOL(unbind_con_driver);
+
+/* unlocked version of unbind_con_driver() */
+int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
+{
 	struct module *owner = csw->owner;
 	const struct consw *defcsw = NULL;
 	struct con_driver *con_driver = NULL, *con_back = NULL;
@@ -3132,7 +3155,7 @@ int unbind_con_driver(const struct consw
 	if (!try_module_get(owner))
 		return -ENODEV;
 
-	console_lock();
+	WARN_CONSOLE_UNLOCKED();
 
 	/* check if driver is registered and if it is unbindable */
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
@@ -3145,10 +3168,8 @@ int unbind_con_driver(const struct consw
 		}
 	}
 
-	if (retval) {
-		console_unlock();
+	if (retval)
 		goto err;
-	}
 
 	retval = -ENODEV;
 
@@ -3164,15 +3185,11 @@ int unbind_con_driver(const struct consw
 		}
 	}
 
-	if (retval) {
-		console_unlock();
+	if (retval)
 		goto err;
-	}
 
-	if (!con_is_bound(csw)) {
-		console_unlock();
+	if (!con_is_bound(csw))
 		goto err;
-	}
 
 	first = max(first, con_driver->first);
 	last = min(last, con_driver->last);
@@ -3199,15 +3216,14 @@ int unbind_con_driver(const struct consw
 	if (!con_is_bound(csw))
 		con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
 
-	console_unlock();
 	/* ignore return value, binding should not fail */
-	bind_con_driver(defcsw, first, last, deflt);
+	do_bind_con_driver(defcsw, first, last, deflt);
 err:
 	module_put(owner);
 	return retval;
 
 }
-EXPORT_SYMBOL(unbind_con_driver);
+EXPORT_SYMBOL_GPL(do_unbind_con_driver);
 
 static int vt_bind(struct con_driver *con)
 {
@@ -3492,28 +3508,18 @@ int con_debug_leave(void)
 }
 EXPORT_SYMBOL_GPL(con_debug_leave);
 
-/**
- * register_con_driver - register console driver to console layer
- * @csw: console driver
- * @first: the first console to take over, minimum value is 0
- * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
- *
- * DESCRIPTION: This function registers a console driver which can later
- * bind to a range of consoles specified by @first and @last. It will
- * also initialize the console driver by calling con_startup().
- */
-int register_con_driver(const struct consw *csw, int first, int last)
+static int do_register_con_driver(const struct consw *csw, int first, int last)
 {
 	struct module *owner = csw->owner;
 	struct con_driver *con_driver;
 	const char *desc;
 	int i, retval = 0;
 
+	WARN_CONSOLE_UNLOCKED();
+
 	if (!try_module_get(owner))
 		return -ENODEV;
 
-	console_lock();
-
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 		con_driver = &registered_con_driver[i];
 
@@ -3566,10 +3572,29 @@ int register_con_driver(const struct con
 	}
 
 err:
-	console_unlock();
 	module_put(owner);
 	return retval;
 }
+
+/**
+ * register_con_driver - register console driver to console layer
+ * @csw: console driver
+ * @first: the first console to take over, minimum value is 0
+ * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
+ *
+ * DESCRIPTION: This function registers a console driver which can later
+ * bind to a range of consoles specified by @first and @last. It will
+ * also initialize the console driver by calling con_startup().
+ */
+int register_con_driver(const struct consw *csw, int first, int last)
+{
+	int retval;
+
+	console_lock();
+	retval = do_register_con_driver(csw, first, last);
+	console_unlock();
+	return retval;
+}
 EXPORT_SYMBOL(register_con_driver);
 
 /**
@@ -3585,9 +3610,18 @@ EXPORT_SYMBOL(register_con_driver);
  */
 int unregister_con_driver(const struct consw *csw)
 {
-	int i, retval = -ENODEV;
+	int retval;
 
 	console_lock();
+	retval = do_unregister_con_driver(csw);
+	console_unlock();
+	return retval;
+}
+EXPORT_SYMBOL(unregister_con_driver);
+
+int do_unregister_con_driver(const struct consw *csw)
+{
+	int i, retval = -ENODEV;
 
 	/* cannot unregister a bound driver */
 	if (con_is_bound(csw))
@@ -3613,27 +3647,53 @@ int unregister_con_driver(const struct c
 		}
 	}
 err:
-	console_unlock();
 	return retval;
 }
-EXPORT_SYMBOL(unregister_con_driver);
+EXPORT_SYMBOL_GPL(do_unregister_con_driver);
 
 /*
  *	If we support more console drivers, this function is used
  *	when a driver wants to take over some existing consoles
  *	and become default driver for newly opened ones.
  *
- *      take_over_console is basically a register followed by unbind
+ *	take_over_console is basically a register followed by unbind
+ */
+int do_take_over_console(const struct consw *csw, int first, int last, int deflt)
+{
+	int err;
+
+	err = do_register_con_driver(csw, first, last);
+	/*
+	 * If we get an busy error we still want to bind the console driver
+	 * and return success, as we may have unbound the console driver
+	 * but not unregistered it.
+	 */
+	if (err == -EBUSY)
+		err = 0;
+	if (!err)
+		do_bind_con_driver(csw, first, last, deflt);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_take_over_console);
+
+/*
+ *	If we support more console drivers, this function is used
+ *	when a driver wants to take over some existing consoles
+ *	and become default driver for newly opened ones.
+ *
+ *	take_over_console is basically a register followed by unbind
  */
 int take_over_console(const struct consw *csw, int first, int last, int deflt)
 {
 	int err;
 
 	err = register_con_driver(csw, first, last);
-	/* if we get an busy error we still want to bind the console driver
+	/*
+	 * If we get an busy error we still want to bind the console driver
 	 * and return success, as we may have unbound the console driver
-	 * but not unregistered it.
-	*/
+	 * but not unregistered it.
+	 */
 	if (err == -EBUSY)
 		err = 0;
 	if (!err)
diff -druNp linux-libre-3.8-gnu1/drivers/usb/chipidea/udc.c linux-libre-3.8.13-gnu1/drivers/usb/chipidea/udc.c
--- linux-libre-3.8-gnu1/drivers/usb/chipidea/udc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/chipidea/udc.c	2013-05-11 16:57:46.000000000 -0400
@@ -461,6 +461,8 @@ static int _hardware_enqueue(struct ci13
 		mReq->ptr->page[i] =
 			(mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
 
+	wmb();
+
 	if (!list_empty(&mEp->qh.queue)) {
 		struct ci13xxx_req *mReqPrev;
 		int n = hw_ep_bit(mEp->num, mEp->dir);
@@ -561,6 +563,12 @@ __acquires(mEp->lock)
 		struct ci13xxx_req *mReq = \
 			list_entry(mEp->qh.queue.next,
 				   struct ci13xxx_req, queue);
+
+		if (mReq->zptr) {
+			dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+			mReq->zptr = NULL;
+		}
+
 		list_del_init(&mReq->queue);
 		mReq->req.status = -ESHUTDOWN;
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/chipidea/udc.h linux-libre-3.8.13-gnu1/drivers/usb/chipidea/udc.h
--- linux-libre-3.8-gnu1/drivers/usb/chipidea/udc.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/chipidea/udc.h	2013-05-11 16:57:46.000000000 -0400
@@ -40,7 +40,7 @@ struct ci13xxx_td {
 #define TD_CURR_OFFSET        (0x0FFFUL <<  0)
 #define TD_FRAME_NUM          (0x07FFUL <<  0)
 #define TD_RESERVED_MASK      (0x0FFFUL <<  0)
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(4)));
 
 /* DMA layout of queue heads */
 struct ci13xxx_qh {
@@ -57,7 +57,7 @@ struct ci13xxx_qh {
 	/* 9 */
 	u32 RESERVED;
 	struct usb_ctrlrequest   setup;
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(4)));
 
 /**
  * struct ci13xxx_req - usb request representation
diff -druNp linux-libre-3.8-gnu1/drivers/usb/class/cdc-acm.c linux-libre-3.8.13-gnu1/drivers/usb/class/cdc-acm.c
--- linux-libre-3.8-gnu1/drivers/usb/class/cdc-acm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/class/cdc-acm.c	2013-05-11 16:57:46.000000000 -0400
@@ -600,7 +600,6 @@ static void acm_port_destruct(struct tty
 
 	dev_dbg(&acm->control->dev, "%s\n", __func__);
 
-	tty_unregister_device(acm_tty_driver, acm->minor);
 	acm_release_minor(acm);
 	usb_put_intf(acm->control);
 	kfree(acm->country_codes);
@@ -1418,6 +1417,8 @@ static void acm_disconnect(struct usb_in
 
 	stop_data_traffic(acm);
 
+	tty_unregister_device(acm_tty_driver, acm->minor);
+
 	usb_free_urb(acm->ctrlurb);
 	for (i = 0; i < ACM_NW; i++)
 		usb_free_urb(acm->wb[i].urb);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/class/cdc-wdm.c linux-libre-3.8.13-gnu1/drivers/usb/class/cdc-wdm.c
--- linux-libre-3.8-gnu1/drivers/usb/class/cdc-wdm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/class/cdc-wdm.c	2013-05-11 16:57:46.000000000 -0400
@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
 #define WDM_RESPONDING		7
 #define WDM_SUSPENDING		8
 #define WDM_RESETTING		9
+#define WDM_OVERFLOW		10
 
 #define WDM_MAX			16
 
@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *
 {
 	struct wdm_device *desc = urb->context;
 	int status = urb->status;
+	int length = urb->actual_length;
 
 	spin_lock(&desc->iuspin);
 	clear_bit(WDM_RESPONDING, &desc->flags);
@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *
 	}
 
 	desc->rerr = status;
-	desc->reslength = urb->actual_length;
-	memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
-	desc->length += desc->reslength;
+	if (length + desc->length > desc->wMaxCommand) {
+		/* The buffer would overflow */
+		set_bit(WDM_OVERFLOW, &desc->flags);
+	} else {
+		/* we may already be in overflow */
+		if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+			memmove(desc->ubuf + desc->length, desc->inbuf, length);
+			desc->length += length;
+			desc->reslength = length;
+		}
+	}
 skip_error:
 	wake_up(&desc->wait);
 
@@ -435,6 +445,11 @@ retry:
 			rv = -ENODEV;
 			goto err;
 		}
+		if (test_bit(WDM_OVERFLOW, &desc->flags)) {
+			clear_bit(WDM_OVERFLOW, &desc->flags);
+			rv = -ENOBUFS;
+			goto err;
+		}
 		i++;
 		if (file->f_flags & O_NONBLOCK) {
 			if (!test_bit(WDM_READ, &desc->flags)) {
@@ -478,6 +493,7 @@ retry:
 			spin_unlock_irq(&desc->iuspin);
 			goto retry;
 		}
+
 		if (!desc->reslength) { /* zero length read */
 			dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
 			clear_bit(WDM_READ, &desc->flags);
@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_int
 	struct wdm_device *desc = wdm_find_device(intf);
 	int rv;
 
+	clear_bit(WDM_OVERFLOW, &desc->flags);
 	clear_bit(WDM_RESETTING, &desc->flags);
 	rv = recover_from_urb_loss(desc);
 	mutex_unlock(&desc->wlock);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/core/devio.c linux-libre-3.8.13-gnu1/drivers/usb/core/devio.c
--- linux-libre-3.8-gnu1/drivers/usb/core/devio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/core/devio.c	2013-05-11 16:57:46.000000000 -0400
@@ -738,6 +738,8 @@ static int check_ctrlrecip(struct dev_st
 	index &= 0xff;
 	switch (requesttype & USB_RECIP_MASK) {
 	case USB_RECIP_ENDPOINT:
+		if ((index & ~USB_DIR_IN) == 0)
+			return 0;
 		ret = findintfep(ps->dev, index);
 		if (ret >= 0)
 			ret = checkintf(ps, ret);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/core/hcd-pci.c linux-libre-3.8.13-gnu1/drivers/usb/core/hcd-pci.c
--- linux-libre-3.8-gnu1/drivers/usb/core/hcd-pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/core/hcd-pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -173,6 +173,7 @@ int usb_hcd_pci_probe(struct pci_dev *de
 	struct hc_driver	*driver;
 	struct usb_hcd		*hcd;
 	int			retval;
+	int			hcd_irq = 0;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -187,15 +188,19 @@ int usb_hcd_pci_probe(struct pci_dev *de
 		return -ENODEV;
 	dev->current_state = PCI_D0;
 
-	/* The xHCI driver supports MSI and MSI-X,
-	 * so don't fail if the BIOS doesn't provide a legacy IRQ.
+	/*
+	 * The xHCI driver has its own irq management
+	 * make sure irq setup is not touched for xhci in generic hcd code
 	 */
-	if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
-		dev_err(&dev->dev,
-			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
-			pci_name(dev));
-		retval = -ENODEV;
-		goto disable_pci;
+	if ((driver->flags & HCD_MASK) != HCD_USB3) {
+		if (!dev->irq) {
+			dev_err(&dev->dev,
+			"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
+				pci_name(dev));
+			retval = -ENODEV;
+			goto disable_pci;
+		}
+		hcd_irq = dev->irq;
 	}
 
 	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
@@ -245,7 +250,7 @@ int usb_hcd_pci_probe(struct pci_dev *de
 
 	pci_set_master(dev);
 
-	retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
+	retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
 	if (retval != 0)
 		goto unmap_registers;
 	set_hs_companion(dev, hcd);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/core/hub.c linux-libre-3.8.13-gnu1/drivers/usb/core/hub.c
--- linux-libre-3.8-gnu1/drivers/usb/core/hub.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/core/hub.c	2013-05-11 16:57:46.000000000 -0400
@@ -2538,70 +2538,35 @@ static int hub_port_wait_reset(struct us
 		if ((portstatus & USB_PORT_STAT_RESET))
 			goto delay;
 
-		/*
-		 * Some buggy devices require a warm reset to be issued even
-		 * when the port appears not to be connected.
-		 */
-		if (!warm) {
-			/*
-			 * Some buggy devices can cause an NEC host controller
-			 * to transition to the "Error" state after a hot port
-			 * reset.  This will show up as the port state in
-			 * "Inactive", and the port may also report a
-			 * disconnect.  Forcing a warm port reset seems to make
-			 * the device work.
-			 *
-			 * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
-			 */
-			if (hub_port_warm_reset_required(hub, portstatus)) {
-				int ret;
+		if (hub_port_warm_reset_required(hub, portstatus))
+			return -ENOTCONN;
 
-				if ((portchange & USB_PORT_STAT_C_CONNECTION))
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_CONNECTION);
-				if (portchange & USB_PORT_STAT_C_LINK_STATE)
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_PORT_LINK_STATE);
-				if (portchange & USB_PORT_STAT_C_RESET)
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_RESET);
-				dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n",
-						port1);
-				ret = hub_port_reset(hub, port1,
-						udev, HUB_BH_RESET_TIME,
-						true);
-				if ((portchange & USB_PORT_STAT_C_CONNECTION))
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_CONNECTION);
-				return ret;
-			}
-			/* Device went away? */
-			if (!(portstatus & USB_PORT_STAT_CONNECTION))
-				return -ENOTCONN;
+		/* Device went away? */
+		if (!(portstatus & USB_PORT_STAT_CONNECTION))
+			return -ENOTCONN;
 
-			/* bomb out completely if the connection bounced */
-			if ((portchange & USB_PORT_STAT_C_CONNECTION))
-				return -ENOTCONN;
+		/* bomb out completely if the connection bounced.  A USB 3.0
+		 * connection may bounce if multiple warm resets were issued,
+		 * but the device may have successfully re-connected. Ignore it.
+		 */
+		if (!hub_is_superspeed(hub->hdev) &&
+				(portchange & USB_PORT_STAT_C_CONNECTION))
+			return -ENOTCONN;
 
-			if ((portstatus & USB_PORT_STAT_ENABLE)) {
-				if (hub_is_wusb(hub))
-					udev->speed = USB_SPEED_WIRELESS;
-				else if (hub_is_superspeed(hub->hdev))
-					udev->speed = USB_SPEED_SUPER;
-				else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
-					udev->speed = USB_SPEED_HIGH;
-				else if (portstatus & USB_PORT_STAT_LOW_SPEED)
-					udev->speed = USB_SPEED_LOW;
-				else
-					udev->speed = USB_SPEED_FULL;
+		if ((portstatus & USB_PORT_STAT_ENABLE)) {
+			if (!udev)
 				return 0;
-			}
-		} else {
-			if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
-					hub_port_warm_reset_required(hub,
-						portstatus))
-				return -ENOTCONN;
 
+			if (hub_is_wusb(hub))
+				udev->speed = USB_SPEED_WIRELESS;
+			else if (hub_is_superspeed(hub->hdev))
+				udev->speed = USB_SPEED_SUPER;
+			else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+				udev->speed = USB_SPEED_HIGH;
+			else if (portstatus & USB_PORT_STAT_LOW_SPEED)
+				udev->speed = USB_SPEED_LOW;
+			else
+				udev->speed = USB_SPEED_FULL;
 			return 0;
 		}
 
@@ -2619,16 +2584,16 @@ delay:
 }
 
 static void hub_port_finish_reset(struct usb_hub *hub, int port1,
-			struct usb_device *udev, int *status, bool warm)
+			struct usb_device *udev, int *status)
 {
 	switch (*status) {
 	case 0:
-		if (!warm) {
-			struct usb_hcd *hcd;
-			/* TRSTRCY = 10 ms; plus some extra */
-			msleep(10 + 40);
+		/* TRSTRCY = 10 ms; plus some extra */
+		msleep(10 + 40);
+		if (udev) {
+			struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
 			update_devnum(udev, 0);
-			hcd = bus_to_hcd(udev->bus);
 			/* The xHC may think the device is already reset,
 			 * so ignore the status.
 			 */
@@ -2640,14 +2605,15 @@ static void hub_port_finish_reset(struct
 	case -ENODEV:
 		clear_port_feature(hub->hdev,
 				port1, USB_PORT_FEAT_C_RESET);
-		/* FIXME need disconnect() for NOTATTACHED device */
 		if (hub_is_superspeed(hub->hdev)) {
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_BH_PORT_RESET);
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_PORT_LINK_STATE);
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_CONNECTION);
 		}
-		if (!warm)
+		if (udev)
 			usb_set_device_state(udev, *status
 					? USB_STATE_NOTATTACHED
 					: USB_STATE_DEFAULT);
@@ -2660,18 +2626,30 @@ static int hub_port_reset(struct usb_hub
 			struct usb_device *udev, unsigned int delay, bool warm)
 {
 	int i, status;
+	u16 portchange, portstatus;
 
-	if (!warm) {
-		/* Block EHCI CF initialization during the port reset.
-		 * Some companion controllers don't like it when they mix.
-		 */
-		down_read(&ehci_cf_port_reset_rwsem);
-	} else {
-		if (!hub_is_superspeed(hub->hdev)) {
+	if (!hub_is_superspeed(hub->hdev)) {
+		if (warm) {
 			dev_err(hub->intfdev, "only USB3 hub support "
 						"warm reset\n");
 			return -EINVAL;
 		}
+		/* Block EHCI CF initialization during the port reset.
+		 * Some companion controllers don't like it when they mix.
+		 */
+		down_read(&ehci_cf_port_reset_rwsem);
+	} else if (!warm) {
+		/*
+		 * If the caller hasn't explicitly requested a warm reset,
+		 * double check and see if one is needed.
+		 */
+		status = hub_port_status(hub, port1,
+					&portstatus, &portchange);
+		if (status < 0)
+			goto done;
+
+		if (hub_port_warm_reset_required(hub, portstatus))
+			warm = true;
 	}
 
 	/* Reset the port */
@@ -2692,10 +2670,33 @@ static int hub_port_reset(struct usb_hub
 						status);
 		}
 
-		/* return on disconnect or reset */
+		/* Check for disconnect or reset */
 		if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
-			hub_port_finish_reset(hub, port1, udev, &status, warm);
-			goto done;
+			hub_port_finish_reset(hub, port1, udev, &status);
+
+			if (!hub_is_superspeed(hub->hdev))
+				goto done;
+
+			/*
+			 * If a USB 3.0 device migrates from reset to an error
+			 * state, re-issue the warm reset.
+			 */
+			if (hub_port_status(hub, port1,
+					&portstatus, &portchange) < 0)
+				goto done;
+
+			if (!hub_port_warm_reset_required(hub, portstatus))
+				goto done;
+
+			/*
+			 * If the port is in SS.Inactive or Compliance Mode, the
+			 * hot or warm reset failed.  Try another warm reset.
+			 */
+			if (!warm) {
+				dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n",
+						port1);
+				warm = true;
+			}
 		}
 
 		dev_dbg (hub->intfdev,
@@ -2709,7 +2710,7 @@ static int hub_port_reset(struct usb_hub
 		port1);
 
 done:
-	if (!warm)
+	if (!hub_is_superspeed(hub->hdev))
 		up_read(&ehci_cf_port_reset_rwsem);
 
 	return status;
@@ -4740,12 +4741,21 @@ static void hub_events(void)
 			 */
 			if (hub_port_warm_reset_required(hub, portstatus)) {
 				int status;
+				struct usb_device *udev =
+					hub->ports[i - 1]->child;
 
 				dev_dbg(hub_dev, "warm reset port %d\n", i);
-				status = hub_port_reset(hub, i, NULL,
-						HUB_BH_RESET_TIME, true);
-				if (status < 0)
-					hub_port_disable(hub, i, 1);
+				if (!udev) {
+					status = hub_port_reset(hub, i,
+							NULL, HUB_BH_RESET_TIME,
+							true);
+					if (status < 0)
+						hub_port_disable(hub, i, 1);
+				} else {
+					usb_lock_device(udev);
+					status = usb_reset_device(udev);
+					usb_unlock_device(udev);
+				}
 				connect_change = 0;
 			}
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/dwc3/core.c linux-libre-3.8.13-gnu1/drivers/usb/dwc3/core.c
--- linux-libre-3.8-gnu1/drivers/usb/dwc3/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/dwc3/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -575,6 +575,7 @@ static int dwc3_remove(struct platform_d
 		break;
 	}
 
+	dwc3_free_event_buffers(dwc);
 	dwc3_core_exit(dwc);
 
 	return 0;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/dwc3/core.h linux-libre-3.8.13-gnu1/drivers/usb/dwc3/core.h
--- linux-libre-3.8-gnu1/drivers/usb/dwc3/core.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/dwc3/core.h	2013-05-11 16:57:46.000000000 -0400
@@ -405,7 +405,6 @@ struct dwc3_event_buffer {
  * @number: endpoint number (1 - 15)
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @resource_index: Resource transfer index
- * @current_uf: Current uf received through last event parameter
  * @interval: the intervall on which the ISOC transfer is started
  * @name: a human readable name e.g. ep1out-bulk
  * @direction: true for TX, false for RX
@@ -439,7 +438,6 @@ struct dwc3_ep {
 	u8			number;
 	u8			type;
 	u8			resource_index;
-	u16			current_uf;
 	u32			interval;
 
 	char			name[20];
diff -druNp linux-libre-3.8-gnu1/drivers/usb/dwc3/gadget.c linux-libre-3.8.13-gnu1/drivers/usb/dwc3/gadget.c
--- linux-libre-3.8-gnu1/drivers/usb/dwc3/gadget.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/dwc3/gadget.c	2013-05-11 16:57:46.000000000 -0400
@@ -754,21 +754,18 @@ static void dwc3_prepare_one_trb(struct
 	struct dwc3		*dwc = dep->dwc;
 	struct dwc3_trb		*trb;
 
-	unsigned int		cur_slot;
-
 	dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n",
 			dep->name, req, (unsigned long long) dma,
 			length, last ? " last" : "",
 			chain ? " chain" : "");
 
-	trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
-	cur_slot = dep->free_slot;
-	dep->free_slot++;
-
 	/* Skip the LINK-TRB on ISOC */
-	if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
+	if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
 			usb_endpoint_xfer_isoc(dep->endpoint.desc))
-		return;
+		dep->free_slot++;
+
+	trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+	dep->free_slot++;
 
 	if (!req->trb) {
 		dwc3_gadget_move_request_queued(req);
@@ -1091,7 +1088,10 @@ static int __dwc3_gadget_ep_queue(struct
 		 * notion of current microframe.
 		 */
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-			dwc3_stop_active_transfer(dwc, dep->number);
+			if (list_empty(&dep->req_queued)) {
+				dwc3_stop_active_transfer(dwc, dep->number);
+				dep->flags = DWC3_EP_ENABLED;
+			}
 			return 0;
 		}
 
@@ -1117,16 +1117,6 @@ static int __dwc3_gadget_ep_queue(struct
 					dep->name);
 	}
 
-	/*
-	 * 3. Missed ISOC Handling. We need to start isoc transfer on the saved
-	 * uframe number.
-	 */
-	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-		(dep->flags & DWC3_EP_MISSED_ISOC)) {
-			__dwc3_gadget_start_isoc(dwc, dep, dep->current_uf);
-			dep->flags &= ~DWC3_EP_MISSED_ISOC;
-	}
-
 	return 0;
 }
 
@@ -1689,14 +1679,29 @@ static int dwc3_cleanup_done_reqs(struct
 				if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
 					dev_dbg(dwc->dev, "incomplete IN transfer %s\n",
 							dep->name);
-					dep->current_uf = event->parameters &
-						~(dep->interval - 1);
+					/*
+					 * If missed isoc occurred and there is
+					 * no request queued then issue END
+					 * TRANSFER, so that core generates
+					 * next xfernotready and we will issue
+					 * a fresh START TRANSFER.
+					 * If there are still queued request
+					 * then wait, do not issue either END
+					 * or UPDATE TRANSFER, just attach next
+					 * request in request_list during
+					 * giveback.If any future queued request
+					 * is successfully transferred then we
+					 * will issue UPDATE TRANSFER for all
+					 * request in the request_list.
+					 */
 					dep->flags |= DWC3_EP_MISSED_ISOC;
 				} else {
 					dev_err(dwc->dev, "incomplete IN transfer %s\n",
 							dep->name);
 					status = -ECONNRESET;
 				}
+			} else {
+				dep->flags &= ~DWC3_EP_MISSED_ISOC;
 			}
 		} else {
 			if (count && (event->status & DEPEVT_STATUS_SHORT))
@@ -1723,6 +1728,23 @@ static int dwc3_cleanup_done_reqs(struct
 			break;
 	} while (1);
 
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+			list_empty(&dep->req_queued)) {
+		if (list_empty(&dep->request_list)) {
+			/*
+			 * If there is no entry in request list then do
+			 * not issue END TRANSFER now. Just set PENDING
+			 * flag, so that END TRANSFER is issued when an
+			 * entry is added into request list.
+			 */
+			dep->flags = DWC3_EP_PENDING_REQUEST;
+		} else {
+			dwc3_stop_active_transfer(dwc, dep->number);
+			dep->flags = DWC3_EP_ENABLED;
+		}
+		return 1;
+	}
+
 	if ((event->status & DEPEVT_STATUS_IOC) &&
 			(trb->ctrl & DWC3_TRB_CTRL_IOC))
 		return 0;
@@ -2157,6 +2179,26 @@ static void dwc3_gadget_conndone_interru
 		break;
 	}
 
+	/* Enable USB2 LPM Capability */
+
+	if ((dwc->revision > DWC3_REVISION_194A)
+			&& (speed != DWC3_DCFG_SUPERSPEED)) {
+		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+		reg |= DWC3_DCFG_LPM_CAP;
+		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+		reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
+
+		/*
+		 * TODO: This should be configurable. For now using
+		 * maximum allowed HIRD threshold value of 0b1100
+		 */
+		reg |= DWC3_DCTL_HIRD_THRES(12);
+
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	}
+
 	/* Recent versions support automatic phy suspend and don't need this */
 	if (dwc->revision < DWC3_REVISION_194A) {
 		/* Suspend unneeded PHY */
@@ -2463,20 +2505,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 			DWC3_DEVTEN_DISCONNEVTEN);
 	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
 
-	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
+	/* automatic phy suspend only on recent versions */
 	if (dwc->revision >= DWC3_REVISION_194A) {
-		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-		reg |= DWC3_DCFG_LPM_CAP;
-		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
-		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-		reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
-
-		/* TODO: This should be configurable */
-		reg |= DWC3_DCTL_HIRD_THRES(28);
-
-		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
 		dwc3_gadget_usb2_phy_suspend(dwc, false);
 		dwc3_gadget_usb3_phy_suspend(dwc, false);
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/usb/gadget/g_ffs.c linux-libre-3.8.13-gnu1/drivers/usb/gadget/g_ffs.c
--- linux-libre-3.8-gnu1/drivers/usb/gadget/g_ffs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/gadget/g_ffs.c	2013-05-11 16:57:46.000000000 -0400
@@ -357,7 +357,7 @@ static int gfs_bind(struct usb_composite
 		goto error;
 	gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
 
-	for (i = func_num; --i; ) {
+	for (i = func_num; i--; ) {
 		ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
 		if (unlikely(ret < 0)) {
 			while (++i < func_num)
@@ -413,7 +413,7 @@ static int gfs_unbind(struct usb_composi
 		gether_cleanup();
 	gfs_ether_setup = false;
 
-	for (i = func_num; --i; )
+	for (i = func_num; i--; )
 		if (ffs_tab[i].ffs_data)
 			functionfs_unbind(ffs_tab[i].ffs_data);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/gadget/udc-core.c linux-libre-3.8.13-gnu1/drivers/usb/gadget/udc-core.c
--- linux-libre-3.8-gnu1/drivers/usb/gadget/udc-core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/gadget/udc-core.c	2013-05-11 16:57:46.000000000 -0400
@@ -265,7 +265,7 @@ static void usb_gadget_remove_driver(str
 		usb_gadget_disconnect(udc->gadget);
 		udc->driver->disconnect(udc->gadget);
 		udc->driver->unbind(udc->gadget);
-		usb_gadget_udc_stop(udc->gadget, udc->driver);
+		usb_gadget_udc_stop(udc->gadget, NULL);
 	} else {
 		usb_gadget_stop(udc->gadget, udc->driver);
 	}
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/ehci-hcd.c linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-hcd.c
--- linux-libre-3.8-gnu1/drivers/usb/host/ehci-hcd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-hcd.c	2013-05-11 16:57:46.000000000 -0400
@@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hc
 
 static void end_unlink_async(struct ehci_hcd *ehci);
 static void unlink_empty_async(struct ehci_hcd *ehci);
+static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
 static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
 static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -669,9 +670,6 @@ int ehci_setup(struct usb_hcd *hcd)
 	if (retval)
 		return retval;
 
-	if (ehci_is_TDI(ehci))
-		tdi_reset(ehci);
-
 	ehci_reset(ehci);
 
 	return 0;
@@ -748,11 +746,9 @@ static irqreturn_t ehci_irq (struct usb_
 		/* guard against (alleged) silicon errata */
 		if (cmd & CMD_IAAD)
 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
-		if (ehci->async_iaa) {
+		if (ehci->async_iaa)
 			COUNT(ehci->stats.iaa);
-			end_unlink_async(ehci);
-		} else
-			ehci_dbg(ehci, "IAA with nothing unlinked?\n");
+		end_unlink_async(ehci);
 	}
 
 	/* remote wakeup [4.3.1] */
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/ehci-hub.c linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-hub.c
--- linux-libre-3.8-gnu1/drivers/usb/host/ehci-hub.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-hub.c	2013-05-11 16:57:46.000000000 -0400
@@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_
 	ehci->rh_state = EHCI_RH_SUSPENDED;
 
 	end_unlink_async(ehci);
-	unlink_empty_async(ehci);
+	unlink_empty_async_suspended(ehci);
 	ehci_handle_intr_unlinks(ehci);
 	end_free_itds(ehci);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/ehci-omap.c linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-omap.c
--- linux-libre-3.8-gnu1/drivers/usb/host/ehci-omap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-omap.c	2013-05-11 16:57:46.000000000 -0400
@@ -288,7 +288,6 @@ static int ehci_hcd_omap_remove(struct p
 {
 	struct device *dev				= &pdev->dev;
 	struct usb_hcd *hcd				= dev_get_drvdata(dev);
-	struct ehci_hcd_omap_platform_data *pdata	= dev->platform_data;
 
 	usb_remove_hcd(hcd);
 	disable_put_regulator(dev->platform_data);
@@ -298,13 +297,6 @@ static int ehci_hcd_omap_remove(struct p
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 
-	if (pdata->phy_reset) {
-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
-			gpio_free(pdata->reset_gpio_port[0]);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
-			gpio_free(pdata->reset_gpio_port[1]);
-	}
 	return 0;
 }
 
@@ -372,7 +364,7 @@ static const struct hc_driver ehci_omap_
 	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
-MODULE_ALIAS("platform:omap-ehci");
+MODULE_ALIAS("platform:ehci-omap");
 MODULE_AUTHOR("Texas Instruments, Inc.");
 MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/ehci-q.c linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-q.c
--- linux-libre-3.8-gnu1/drivers/usb/host/ehci-q.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-q.c	2013-05-11 16:57:46.000000000 -0400
@@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struc
 		 * qtd is updated in qh_completions(). Update the QH
 		 * overlay here.
 		 */
-		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
 			qh->hw->hw_qtd_next = qtd->hw_next;
 			qtd = NULL;
 		}
@@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, s
 			else if (last_status == -EINPROGRESS && !urb->unlinked)
 				continue;
 
-			/* qh unlinked; token in overlay may be most current */
-			if (state == QH_STATE_IDLE
-					&& cpu_to_hc32(ehci, qtd->qtd_dma)
-						== hw->hw_current) {
+			/*
+			 * If this was the active qtd when the qh was unlinked
+			 * and the overlay's token is active, then the overlay
+			 * hasn't been written back to the qtd yet so use its
+			 * token instead of the qtd's.  After the qtd is
+			 * processed and removed, the overlay won't be valid
+			 * any more.
+			 */
+			if (state == QH_STATE_IDLE &&
+					qh->qtd_list.next == &qtd->qtd_list &&
+					(hw->hw_token & ACTIVE_BIT(ehci))) {
 				token = hc32_to_cpu(ehci, hw->hw_token);
+				hw->hw_token &= ~ACTIVE_BIT(ehci);
 
 				/* An unlink may leave an incomplete
 				 * async transaction in the TT buffer.
@@ -1170,7 +1178,7 @@ static void single_unlink_async(struct e
 	struct ehci_qh		*prev;
 
 	/* Add to the end of the list of QHs waiting for the next IAAD */
-	qh->qh_state = QH_STATE_UNLINK;
+	qh->qh_state = QH_STATE_UNLINK_WAIT;
 	if (ehci->async_unlink)
 		ehci->async_unlink_last->unlink_next = qh;
 	else
@@ -1213,9 +1221,19 @@ static void start_iaa_cycle(struct ehci_
 
 		/* Do only the first waiting QH (nVidia bug?) */
 		qh = ehci->async_unlink;
-		ehci->async_iaa = qh;
-		ehci->async_unlink = qh->unlink_next;
-		qh->unlink_next = NULL;
+
+		/*
+		 * Intel (?) bug: The HC can write back the overlay region
+		 * even after the IAA interrupt occurs.  In self-defense,
+		 * always go through two IAA cycles for each QH.
+		 */
+		if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
+			qh->qh_state = QH_STATE_UNLINK;
+		} else {
+			ehci->async_iaa = qh;
+			ehci->async_unlink = qh->unlink_next;
+			qh->unlink_next = NULL;
+		}
 
 		/* Make sure the unlinks are all visible to the hardware */
 		wmb();
@@ -1298,6 +1316,19 @@ static void unlink_empty_async(struct eh
 	}
 }
 
+/* The root hub is suspended; unlink all the async QHs */
+static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+{
+	struct ehci_qh		*qh;
+
+	while (ehci->async->qh_next.qh) {
+		qh = ehci->async->qh_next.qh;
+		WARN_ON(!list_empty(&qh->qtd_list));
+		single_unlink_async(ehci, qh);
+	}
+	start_iaa_cycle(ehci, false);
+}
+
 /* makes sure the async qh will become idle */
 /* caller must own ehci->lock */
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/ehci-sched.c linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-sched.c
--- linux-libre-3.8-gnu1/drivers/usb/host/ehci-sched.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-sched.c	2013-05-11 16:57:46.000000000 -0400
@@ -1214,6 +1214,7 @@ itd_urb_transaction (
 
 		memset (itd, 0, sizeof *itd);
 		itd->itd_dma = itd_dma;
+		itd->frame = 9999;		/* an invalid value */
 		list_add (&itd->itd_list, &sched->td_list);
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1915,6 +1916,7 @@ sitd_urb_transaction (
 
 		memset (sitd, 0, sizeof *sitd);
 		sitd->sitd_dma = sitd_dma;
+		sitd->frame = 9999;		/* an invalid value */
 		list_add (&sitd->sitd_list, &iso_sched->td_list);
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/ehci-timer.c linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-timer.c
--- linux-libre-3.8-gnu1/drivers/usb/host/ehci-timer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/ehci-timer.c	2013-05-11 16:57:46.000000000 -0400
@@ -113,15 +113,14 @@ static void ehci_poll_ASS(struct ehci_hc
 
 	if (want != actual) {
 
-		/* Poll again later */
-		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
-		++ehci->ASS_poll_count;
-		return;
+		/* Poll again later, but give up after about 20 ms */
+		if (ehci->ASS_poll_count++ < 20) {
+			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+			return;
+		}
+		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
+				want, actual);
 	}
-
-	if (ehci->ASS_poll_count > 20)
-		ehci_dbg(ehci, "ASS poll count reached %d\n",
-				ehci->ASS_poll_count);
 	ehci->ASS_poll_count = 0;
 
 	/* The status is up-to-date; restart or stop the schedule as needed */
@@ -160,14 +159,14 @@ static void ehci_poll_PSS(struct ehci_hc
 
 	if (want != actual) {
 
-		/* Poll again later */
-		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
-		return;
+		/* Poll again later, but give up after about 20 ms */
+		if (ehci->PSS_poll_count++ < 20) {
+			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+			return;
+		}
+		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
+				want, actual);
 	}
-
-	if (ehci->PSS_poll_count > 20)
-		ehci_dbg(ehci, "PSS poll count reached %d\n",
-				ehci->PSS_poll_count);
 	ehci->PSS_poll_count = 0;
 
 	/* The status is up-to-date; restart or stop the schedule as needed */
@@ -305,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehc
 	 * (a) SMP races against real IAA firing and retriggering, and
 	 * (b) clean HC shutdown, when IAA watchdog was pending.
 	 */
-	if (ehci->async_iaa) {
+	if (1) {
 		u32 cmd, status;
 
 		/* If we get here, IAA is *REALLY* late.  It's barely
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/xhci.c linux-libre-3.8.13-gnu1/drivers/usb/host/xhci.c
--- linux-libre-3.8-gnu1/drivers/usb/host/xhci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/xhci.c	2013-05-11 16:57:46.000000000 -0400
@@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct us
 	 * generate interrupts.  Don't even try to enable MSI.
 	 */
 	if (xhci->quirks & XHCI_BROKEN_MSI)
-		return 0;
+		goto legacy_irq;
 
 	/* unregister the legacy interrupt */
 	if (hcd->irq)
@@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct us
 		return -EINVAL;
 	}
 
+ legacy_irq:
 	/* fall back to legacy interrupt*/
 	ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
 			hcd->irq_descr, hcd);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/xhci.h linux-libre-3.8.13-gnu1/drivers/usb/host/xhci.h
--- linux-libre-3.8-gnu1/drivers/usb/host/xhci.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/xhci.h	2013-05-11 16:57:46.000000000 -0400
@@ -206,8 +206,8 @@ struct xhci_op_regs {
 /* bits 12:31 are reserved (and should be preserved on writes). */
 
 /* IMAN - Interrupt Management Register */
-#define IMAN_IP		(1 << 1)
-#define IMAN_IE		(1 << 0)
+#define IMAN_IE		(1 << 1)
+#define IMAN_IP		(1 << 0)
 
 /* USBSTS - USB status - status bitmasks */
 /* HC not running - set to 1 when run/stop bit is cleared. */
@@ -972,6 +972,10 @@ struct xhci_transfer_event {
 	__le32	flags;
 };
 
+/* Transfer event TRB length bit mask */
+/* bits 0:23 */
+#define	EVENT_TRB_LEN(p)		((p) & 0xffffff)
+
 /** Transfer Event bit fields **/
 #define	TRB_TO_EP_ID(p)	(((p) >> 16) & 0x1f)
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/host/xhci-ring.c linux-libre-3.8.13-gnu1/drivers/usb/host/xhci-ring.c
--- linux-libre-3.8-gnu1/drivers/usb/host/xhci-ring.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/host/xhci-ring.c	2013-05-11 16:57:46.000000000 -0400
@@ -2027,8 +2027,8 @@ static int process_ctrl_td(struct xhci_h
 		if (event_trb != ep_ring->dequeue &&
 				event_trb != td->last_trb)
 			td->urb->actual_length =
-				td->urb->transfer_buffer_length
-				- TRB_LEN(le32_to_cpu(event->transfer_len));
+				td->urb->transfer_buffer_length -
+				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 		else
 			td->urb->actual_length = 0;
 
@@ -2060,7 +2060,7 @@ static int process_ctrl_td(struct xhci_h
 		/* Maybe the event was for the data stage? */
 			td->urb->actual_length =
 				td->urb->transfer_buffer_length -
-				TRB_LEN(le32_to_cpu(event->transfer_len));
+				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 			xhci_dbg(xhci, "Waiting for status "
 					"stage event\n");
 			return 0;
@@ -2096,7 +2096,7 @@ static int process_isoc_td(struct xhci_h
 	/* handle completion code */
 	switch (trb_comp_code) {
 	case COMP_SUCCESS:
-		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
 			frame->status = 0;
 			break;
 		}
@@ -2141,7 +2141,7 @@ static int process_isoc_td(struct xhci_h
 				len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
 		}
 		len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
-			TRB_LEN(le32_to_cpu(event->transfer_len));
+			EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 
 		if (trb_comp_code != COMP_STOP_INVAL) {
 			frame->actual_length = len;
@@ -2199,7 +2199,7 @@ static int process_bulk_intr_td(struct x
 	case COMP_SUCCESS:
 		/* Double check that the HW transferred everything. */
 		if (event_trb != td->last_trb ||
-				TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+		    EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
 			xhci_warn(xhci, "WARN Successful completion "
 					"on short TX\n");
 			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -2227,18 +2227,18 @@ static int process_bulk_intr_td(struct x
 				"%d bytes untransferred\n",
 				td->urb->ep->desc.bEndpointAddress,
 				td->urb->transfer_buffer_length,
-				TRB_LEN(le32_to_cpu(event->transfer_len)));
+				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
 	/* Fast path - was this the last TRB in the TD for this URB? */
 	if (event_trb == td->last_trb) {
-		if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
 			td->urb->actual_length =
 				td->urb->transfer_buffer_length -
-				TRB_LEN(le32_to_cpu(event->transfer_len));
+				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 			if (td->urb->transfer_buffer_length <
 					td->urb->actual_length) {
 				xhci_warn(xhci, "HC gave bad length "
 						"of %d bytes left\n",
-					  TRB_LEN(le32_to_cpu(event->transfer_len)));
+					  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
 				td->urb->actual_length = 0;
 				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
 					*status = -EREMOTEIO;
@@ -2280,7 +2280,7 @@ static int process_bulk_intr_td(struct x
 		if (trb_comp_code != COMP_STOP_INVAL)
 			td->urb->actual_length +=
 				TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
-				TRB_LEN(le32_to_cpu(event->transfer_len));
+				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 	}
 
 	return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2368,7 +2368,7 @@ static int handle_tx_event(struct xhci_h
 	 * transfer type
 	 */
 	case COMP_SUCCESS:
-		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
 			break;
 		if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
 			trb_comp_code = COMP_SHORT_TX;
@@ -2461,14 +2461,21 @@ static int handle_tx_event(struct xhci_h
 		 * TD list.
 		 */
 		if (list_empty(&ep_ring->td_list)) {
-			xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
-					"with no TDs queued?\n",
-				  TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
-				  ep_index);
-			xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
-				 (le32_to_cpu(event->flags) &
-				  TRB_TYPE_BITMASK)>>10);
-			xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+			/*
+			 * A stopped endpoint may generate an extra completion
+			 * event if the device was suspended.  Don't print
+			 * warnings.
+			 */
+			if (!(trb_comp_code == COMP_STOP ||
+						trb_comp_code == COMP_STOP_INVAL)) {
+				xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+						TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
+						ep_index);
+				xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+						(le32_to_cpu(event->flags) &
+						 TRB_TYPE_BITMASK)>>10);
+				xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+			}
 			if (ep->skip) {
 				ep->skip = false;
 				xhci_dbg(xhci, "td_list is empty while skip "
diff -druNp linux-libre-3.8-gnu1/drivers/usb/misc/appledisplay.c linux-libre-3.8.13-gnu1/drivers/usb/misc/appledisplay.c
--- linux-libre-3.8-gnu1/drivers/usb/misc/appledisplay.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/misc/appledisplay.c	2013-05-11 16:57:46.000000000 -0400
@@ -63,6 +63,7 @@ static const struct usb_device_id appled
 	{ APPLEDISPLAY_DEVICE(0x9219) },
 	{ APPLEDISPLAY_DEVICE(0x921c) },
 	{ APPLEDISPLAY_DEVICE(0x921d) },
+	{ APPLEDISPLAY_DEVICE(0x9236) },
 
 	/* Terminating entry */
 	{ }
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/am35x.c linux-libre-3.8.13-gnu1/drivers/usb/musb/am35x.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/am35x.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/am35x.c	2013-05-11 16:57:46.000000000 -0400
@@ -365,7 +365,7 @@ static int am35x_musb_init(struct musb *
 	usb_nop_xceiv_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv))
-		return -ENODEV;
+		return -EPROBE_DEFER;
 
 	setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/blackfin.c linux-libre-3.8.13-gnu1/drivers/usb/musb/blackfin.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/blackfin.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/blackfin.c	2013-05-11 16:57:46.000000000 -0400
@@ -406,7 +406,7 @@ static int bfin_musb_init(struct musb *m
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv)) {
 		gpio_free(musb->config->gpio_vrsel);
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 
 	bfin_musb_reg_init(musb);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/da8xx.c linux-libre-3.8.13-gnu1/drivers/usb/musb/da8xx.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/da8xx.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/da8xx.c	2013-05-11 16:57:46.000000000 -0400
@@ -327,7 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(
 		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
 		int err;
 
-		err = musb->int_usb & USB_INTR_VBUSERROR;
+		err = musb->int_usb & MUSB_INTR_VBUSERROR;
 		if (err) {
 			/*
 			 * The Mentor core doesn't debounce VBUS as needed
@@ -410,6 +410,7 @@ static int da8xx_musb_init(struct musb *
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 rev;
+	int ret = -ENODEV;
 
 	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
 
@@ -420,8 +421,10 @@ static int da8xx_musb_init(struct musb *
 
 	usb_nop_xceiv_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(musb->xceiv))
+	if (IS_ERR_OR_NULL(musb->xceiv)) {
+		ret = -EPROBE_DEFER;
 		goto fail;
+	}
 
 	setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
 
@@ -441,7 +444,7 @@ static int da8xx_musb_init(struct musb *
 	musb->isr = da8xx_musb_interrupt;
 	return 0;
 fail:
-	return -ENODEV;
+	return ret;
 }
 
 static int da8xx_musb_exit(struct musb *musb)
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/davinci.c linux-libre-3.8.13-gnu1/drivers/usb/musb/davinci.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/davinci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/davinci.c	2013-05-11 16:57:46.000000000 -0400
@@ -380,11 +380,14 @@ static int davinci_musb_init(struct musb
 {
 	void __iomem	*tibase = musb->ctrl_base;
 	u32		revision;
+	int 		ret = -ENODEV;
 
 	usb_nop_xceiv_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(musb->xceiv))
+	if (IS_ERR_OR_NULL(musb->xceiv)) {
+		ret = -EPROBE_DEFER;
 		goto unregister;
+	}
 
 	musb->mregs += DAVINCI_BASE_OFFSET;
 
@@ -438,7 +441,7 @@ fail:
 	usb_put_phy(musb->xceiv);
 unregister:
 	usb_nop_xceiv_unregister();
-	return -ENODEV;
+	return ret;
 }
 
 static int davinci_musb_exit(struct musb *musb)
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/musb_core.c linux-libre-3.8.13-gnu1/drivers/usb/musb/musb_core.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/musb_core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/musb_core.c	2013-05-11 16:57:46.000000000 -0400
@@ -1993,6 +1993,7 @@ fail2:
 	musb_platform_exit(musb);
 
 fail1:
+	pm_runtime_disable(musb->controller);
 	dev_err(musb->controller,
 		"musb_init_controller failed with status %d\n", status);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/musb_dsps.c linux-libre-3.8.13-gnu1/drivers/usb/musb/musb_dsps.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/musb_dsps.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/musb_dsps.c	2013-05-11 16:57:46.000000000 -0400
@@ -419,7 +419,7 @@ static int dsps_musb_init(struct musb *m
 	usb_nop_xceiv_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv))
-		return -ENODEV;
+		return -EPROBE_DEFER;
 
 	/* Returns zero if e.g. not clocked */
 	rev = dsps_readl(reg_base, wrp->revision);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/omap2430.c linux-libre-3.8.13-gnu1/drivers/usb/musb/omap2430.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/omap2430.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/omap2430.c	2013-05-11 16:57:46.000000000 -0400
@@ -369,7 +369,7 @@ static int omap2430_musb_init(struct mus
 	musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv)) {
 		pr_err("HS USB OTG: no transceiver configured\n");
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 
 	musb->isr = omap2430_musb_interrupt;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/tusb6010.c linux-libre-3.8.13-gnu1/drivers/usb/musb/tusb6010.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/tusb6010.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/tusb6010.c	2013-05-11 16:57:46.000000000 -0400
@@ -1069,7 +1069,7 @@ static int tusb_musb_init(struct musb *m
 	usb_nop_xceiv_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv))
-		return -ENODEV;
+		return -EPROBE_DEFER;
 
 	pdev = to_platform_device(musb->controller);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/musb/ux500.c linux-libre-3.8.13-gnu1/drivers/usb/musb/ux500.c
--- linux-libre-3.8-gnu1/drivers/usb/musb/ux500.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/musb/ux500.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,7 +61,7 @@ static int ux500_musb_init(struct musb *
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv)) {
 		pr_err("HS USB OTG: no transceiver configured\n");
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 
 	musb->isr = ux500_musb_interrupt;
@@ -108,7 +108,7 @@ static int ux500_probe(struct platform_d
 		goto err3;
 	}
 
-	ret = clk_enable(clk);
+	ret = clk_prepare_enable(clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
 		goto err4;
@@ -148,7 +148,7 @@ static int ux500_probe(struct platform_d
 	return 0;
 
 err5:
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 
 err4:
 	clk_put(clk);
@@ -168,7 +168,7 @@ static int ux500_remove(struct platform_
 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
-	clk_disable(glue->clk);
+	clk_disable_unprepare(glue->clk);
 	clk_put(glue->clk);
 	kfree(glue);
 
@@ -182,7 +182,7 @@ static int ux500_suspend(struct device *
 	struct musb		*musb = glue_to_musb(glue);
 
 	usb_phy_set_suspend(musb->xceiv, 1);
-	clk_disable(glue->clk);
+	clk_disable_unprepare(glue->clk);
 
 	return 0;
 }
@@ -193,7 +193,7 @@ static int ux500_resume(struct device *d
 	struct musb		*musb = glue_to_musb(glue);
 	int			ret;
 
-	ret = clk_enable(glue->clk);
+	ret = clk_prepare_enable(glue->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable clock\n");
 		return ret;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/ark3116.c linux-libre-3.8.13-gnu1/drivers/usb/serial/ark3116.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/ark3116.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/ark3116.c	2013-05-11 16:57:46.000000000 -0400
@@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *se
 }
 
 struct ark3116_private {
-	wait_queue_head_t       delta_msr_wait;
 	struct async_icount	icount;
 	int			irda;	/* 1 for irda device */
 
@@ -146,7 +145,6 @@ static int ark3116_port_probe(struct usb
 	if (!priv)
 		return -ENOMEM;
 
-	init_waitqueue_head(&priv->delta_msr_wait);
 	mutex_init(&priv->hw_lock);
 	spin_lock_init(&priv->status_lock);
 
@@ -456,10 +454,14 @@ static int ark3116_ioctl(struct tty_stru
 	case TIOCMIWAIT:
 		for (;;) {
 			struct async_icount prev = priv->icount;
-			interruptible_sleep_on(&priv->delta_msr_wait);
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			if ((prev.rng == priv->icount.rng) &&
 			    (prev.dsr == priv->icount.dsr) &&
 			    (prev.dcd == priv->icount.dcd) &&
@@ -580,7 +582,7 @@ static void ark3116_update_msr(struct us
 			priv->icount.dcd++;
 		if (msr & UART_MSR_TERI)
 			priv->icount.rng++;
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/ch341.c linux-libre-3.8.13-gnu1/drivers/usb/serial/ch341.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/ch341.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/ch341.c	2013-05-11 16:57:46.000000000 -0400
@@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 struct ch341_private {
 	spinlock_t lock; /* access lock */
-	wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
 	unsigned baud_rate; /* set baud rate */
 	u8 line_control; /* set line control value RTS/DTR */
 	u8 line_status; /* active status of modem control inputs */
@@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_s
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 	priv->baud_rate = DEFAULT_BAUD_RATE;
 	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
@@ -298,7 +296,7 @@ static void ch341_dtr_rts(struct usb_ser
 		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
 	spin_unlock_irqrestore(&priv->lock, flags);
 	ch341_set_handshake(port->serial->dev, priv->line_control);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 }
 
 static void ch341_close(struct usb_serial_port *port)
@@ -491,7 +489,7 @@ static void ch341_read_int_callback(stru
 			tty_kref_put(tty);
 		}
 
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 
 exit:
@@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (!multi_change) {
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		multi_change = priv->multi_status_change;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/cp210x.c linux-libre-3.8.13-gnu1/drivers/usb/serial/cp210x.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/cp210x.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/cp210x.c	2013-05-11 16:57:46.000000000 -0400
@@ -85,6 +85,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
 	{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
 	{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+	{ USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */
 	{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
 	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
 	{ USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
@@ -150,6 +151,25 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
 	{ USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
 	{ USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
+	{ USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */
+	{ USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */
+	{ USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */
+	{ USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */
+	{ USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */
+	{ USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */
+	{ USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */
+	{ USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */
+	{ USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */
+	{ USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */
+	{ USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */
+	{ USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */
+	{ USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */
+	{ USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */
+	{ USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */
+	{ USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */
+	{ USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+	{ USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+	{ USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
 	{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
 	{ USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
 	{ USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/cypress_m8.c linux-libre-3.8.13-gnu1/drivers/usb/serial/cypress_m8.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/cypress_m8.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/cypress_m8.c	2013-05-11 16:57:46.000000000 -0400
@@ -111,7 +111,6 @@ struct cypress_private {
 	int baud_rate;			   /* stores current baud rate in
 					      integer form */
 	int isthrottled;		   /* if throttled, discard reads */
-	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
 	char prev_status, diff_status;	   /* used for TIOCMIWAIT */
 	/* we pass a pointer to this as the argument sent to
 	   cypress_set_termios old_termios */
@@ -449,7 +448,6 @@ static int cypress_generic_port_probe(st
 		kfree(priv);
 		return -ENOMEM;
 	}
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	usb_reset_configuration(serial->dev);
 
@@ -868,12 +866,16 @@ static int cypress_ioctl(struct tty_stru
 	switch (cmd) {
 	/* This code comes from drivers/char/serial.c and ftdi_sio.c */
 	case TIOCMIWAIT:
-		while (priv != NULL) {
-			interruptible_sleep_on(&priv->delta_msr_wait);
+		for (;;) {
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
-			else {
+
+			if (port->serial->disconnected)
+				return -EIO;
+
+			{
 				char diff = priv->diff_status;
 				if (diff == 0)
 					return -EIO; /* no change => error */
@@ -1187,7 +1189,7 @@ static void cypress_read_int_callback(st
 	if (priv->current_status != priv->prev_status) {
 		priv->diff_status |= priv->current_status ^
 			priv->prev_status;
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 		priv->prev_status = priv->current_status;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/f81232.c linux-libre-3.8.13-gnu1/drivers/usb/serial/f81232.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/f81232.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/f81232.c	2013-05-11 16:57:46.000000000 -0400
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 struct f81232_private {
 	spinlock_t lock;
-	wait_queue_head_t delta_msr_wait;
 	u8 line_control;
 	u8 line_status;
 };
@@ -112,7 +111,7 @@ static void f81232_process_read_urb(stru
 	line_status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
@@ -261,11 +260,14 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -327,7 +329,6 @@ static int f81232_port_probe(struct usb_
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	usb_set_serial_port_data(port, priv);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/ftdi_sio.c linux-libre-3.8.13-gnu1/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/ftdi_sio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/ftdi_sio.c	2013-05-11 16:57:46.000000000 -0400
@@ -69,9 +69,7 @@ struct ftdi_private {
 	int flags;		/* some ASYNC_xxxx flags are supported */
 	unsigned long last_dtr_rts;	/* saved modem control outputs */
 	struct async_icount	icount;
-	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	char prev_status;        /* Used for TIOCMIWAIT */
-	bool dev_gone;        /* Used to abort TIOCMIWAIT */
 	char transmit_empty;	/* If transmitter is empty or not */
 	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface
 				   (0 for FT232/245) */
@@ -191,6 +189,7 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },
 	{ USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -642,6 +641,7 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
 	{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
 	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
+	{ USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
@@ -871,7 +871,9 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
 	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
+	{ USB_DEVICE(ST_VID, ST_STMCLT_2232_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
@@ -1691,10 +1693,8 @@ static int ftdi_sio_port_probe(struct us
 
 	kref_init(&priv->kref);
 	mutex_init(&priv->cfg_lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	priv->flags = ASYNC_LOW_LATENCY;
-	priv->dev_gone = false;
 
 	if (quirk && quirk->port_probe)
 		quirk->port_probe(priv);
@@ -1795,20 +1795,24 @@ static int ftdi_8u2232c_probe(struct usb
 }
 
 /*
- * First and second port on STMCLiteadaptors is reserved for JTAG interface
- * and the forth port for pio
+ * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's
+ * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and
+ * can be accessed from userspace.
+ * The next two ports are enabled as UARTs by default, where port 2 is
+ * a conventional RS-232 UART.
  */
 static int ftdi_stmclite_probe(struct usb_serial *serial)
 {
 	struct usb_device *udev = serial->dev;
 	struct usb_interface *interface = serial->interface;
 
-	if (interface == udev->actconfig->interface[2])
-		return 0;
-
-	dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+	if (interface == udev->actconfig->interface[0] ||
+	    interface == udev->actconfig->interface[1]) {
+		dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+		return -ENODEV;
+	}
 
-	return -ENODEV;
+	return 0;
 }
 
 /*
@@ -1840,8 +1844,7 @@ static int ftdi_sio_port_remove(struct u
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-	priv->dev_gone = true;
-	wake_up_interruptible_all(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	remove_sysfs_attrs(port);
 
@@ -1886,24 +1889,22 @@ static void ftdi_dtr_rts(struct usb_seri
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected) {
-		/* Disable flow control */
-		if (!on && usb_control_msg(port->serial->dev,
+	/* Disable flow control */
+	if (!on) {
+		if (usb_control_msg(port->serial->dev,
 			    usb_sndctrlpipe(port->serial->dev, 0),
 			    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 			    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 			    0, priv->interface, NULL, 0,
 			    WDR_TIMEOUT) < 0) {
-			    dev_err(&port->dev, "error from flowcontrol urb\n");
+			dev_err(&port->dev, "error from flowcontrol urb\n");
 		}
-		/* drop RTS and DTR */
-		if (on)
-			set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-		else
-			clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	}
-	mutex_unlock(&port->serial->disc_mutex);
+	/* drop RTS and DTR */
+	if (on)
+		set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+	else
+		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 }
 
 /*
@@ -1992,7 +1993,7 @@ static int ftdi_process_packet(struct tt
 		if (diff_status & FTDI_RS0_RLSD)
 			priv->icount.dcd++;
 
-		wake_up_interruptible_all(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 		priv->prev_status = status;
 	}
 
@@ -2449,11 +2450,15 @@ static int ftdi_ioctl(struct tty_struct
 	 */
 	case TIOCMIWAIT:
 		cprev = priv->icount;
-		while (!priv->dev_gone) {
-			interruptible_sleep_on(&priv->delta_msr_wait);
+		for (;;) {
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = priv->icount;
 			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
 			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
@@ -2463,8 +2468,6 @@ static int ftdi_ioctl(struct tty_struct
 			}
 			cprev = cnow;
 		}
-		return -EIO;
-		break;
 	case TIOCSERGETLSR:
 		return get_lsr_info(port, (struct serial_struct __user *)arg);
 		break;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/ftdi_sio_ids.h linux-libre-3.8.13-gnu1/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-3.8-gnu1/drivers/usb/serial/ftdi_sio_ids.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/ftdi_sio_ids.h	2013-05-11 16:57:46.000000000 -0400
@@ -74,6 +74,7 @@
 #define FTDI_OPENDCC_THROTTLE_PID	0xBFDA
 #define FTDI_OPENDCC_GATEWAY_PID	0xBFDB
 #define FTDI_OPENDCC_GBM_PID	0xBFDC
+#define FTDI_OPENDCC_GBM_BOOST_PID	0xBFDD
 
 /* NZR SEM 16+ USB (http://www.nzr.de) */
 #define FTDI_NZR_SEM_USB_PID	0xC1E0	/* NZR SEM-LOG16+ */
@@ -584,6 +585,13 @@
 #define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */
 
 /*
+ * Mitsubishi Electric Corp. (http://www.meau.com)
+ * Submitted by Konstantin Holoborodko
+ */
+#define MITSUBISHI_VID		0x06D3
+#define MITSUBISHI_FXUSB_PID	0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
+
+/*
  * Definitions for B&B Electronics products.
  */
 #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */
@@ -1143,7 +1151,8 @@
  * STMicroelectonics
  */
 #define ST_VID			0x0483
-#define ST_STMCLT1030_PID	0x3747 /* ST Micro Connect Lite STMCLT1030 */
+#define ST_STMCLT_2232_PID	0x3746
+#define ST_STMCLT_4232_PID	0x3747
 
 /*
  * Papouch products (http://www.papouch.com/)
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/garmin_gps.c linux-libre-3.8.13-gnu1/drivers/usb/serial/garmin_gps.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/garmin_gps.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/garmin_gps.c	2013-05-11 16:57:46.000000000 -0400
@@ -959,10 +959,7 @@ static void garmin_close(struct usb_seri
 	if (!serial)
 		return;
 
-	mutex_lock(&port->serial->disc_mutex);
-
-	if (!port->serial->disconnected)
-		garmin_clear(garmin_data_p);
+	garmin_clear(garmin_data_p);
 
 	/* shutdown our urbs */
 	usb_kill_urb(port->read_urb);
@@ -971,8 +968,6 @@ static void garmin_close(struct usb_seri
 	/* keep reset state so we know that we must start a new session */
 	if (garmin_data_p->state != STATE_RESET)
 		garmin_data_p->state = STATE_DISCONNECTED;
-
-	mutex_unlock(&port->serial->disc_mutex);
 }
 
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/io_edgeport.c linux-libre-3.8.13-gnu1/drivers/usb/serial/io_edgeport.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/io_edgeport.c	2013-05-01 16:48:37.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/io_edgeport.c	2013-05-11 19:24:25.000000000 -0400
@@ -110,7 +110,6 @@ struct edgeport_port {
 	wait_queue_head_t	wait_chase;		/* for handling sleeping while waiting for chase to finish */
 	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */
 	wait_queue_head_t	wait_command;		/* for handling sleeping while waiting for command to finish */
-	wait_queue_head_t	delta_msr_wait;		/* for handling sleeping while waiting for msr change to happen */
 
 	struct async_icount	icount;
 	struct usb_serial_port	*port;			/* loop back to the owner of this object */
@@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *
 	/* initialize our wait queues */
 	init_waitqueue_head(&edge_port->wait_open);
 	init_waitqueue_head(&edge_port->wait_chase);
-	init_waitqueue_head(&edge_port->delta_msr_wait);
 	init_waitqueue_head(&edge_port->wait_command);
 
 	/* initialize our icount structure */
@@ -1669,13 +1667,17 @@ static int edge_ioctl(struct tty_struct
 		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
 		cprev = edge_port->icount;
 		while (1) {
-			prepare_to_wait(&edge_port->delta_msr_wait,
+			prepare_to_wait(&port->delta_msr_wait,
 						&wait, TASK_INTERRUPTIBLE);
 			schedule();
-			finish_wait(&edge_port->delta_msr_wait, &wait);
+			finish_wait(&port->delta_msr_wait, &wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = edge_port->icount;
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2055,7 +2057,7 @@ static void handle_new_msr(struct edgepo
 			icount->dcd++;
 		if (newMsr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&edge_port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->port->delta_msr_wait);
 	}
 
 	/* Save the new modem status */
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/io_ti.c linux-libre-3.8.13-gnu1/drivers/usb/serial/io_ti.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/io_ti.c	2013-05-01 16:48:41.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/io_ti.c	2013-05-11 19:24:29.000000000 -0400
@@ -87,9 +87,6 @@ struct edgeport_port {
 	int close_pending;
 	int lsr_event;
 	struct async_icount	icount;
-	wait_queue_head_t	delta_msr_wait;	/* for handling sleeping while
-						   waiting for msr change to
-						   happen */
 	struct edgeport_serial	*edge_serial;
 	struct usb_serial_port	*port;
 	__u8 bUartMode;		/* Port type, 0: RS232, etc. */
@@ -1518,7 +1515,7 @@ static void handle_new_msr(struct edgepo
 			icount->dcd++;
 		if (msr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&edge_port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->port->delta_msr_wait);
 	}
 
 	/* Save the new modem status */
@@ -1821,7 +1818,6 @@ static int edge_open(struct tty_struct *
 	dev = port->serial->dev;
 
 	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-	init_waitqueue_head(&edge_port->delta_msr_wait);
 
 	/* turn off loopback */
 	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
@@ -2488,10 +2484,14 @@ static int edge_ioctl(struct tty_struct
 		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
 		cprev = edge_port->icount;
 		while (1) {
-			interruptible_sleep_on(&edge_port->delta_msr_wait);
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = edge_port->icount;
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2702,6 +2702,7 @@ static struct usb_serial_driver edgeport
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/mct_u232.c linux-libre-3.8.13-gnu1/drivers/usb/serial/mct_u232.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/mct_u232.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/mct_u232.c	2013-05-11 16:57:46.000000000 -0400
@@ -114,8 +114,6 @@ struct mct_u232_private {
 	unsigned char	     last_msr;      /* Modem Status Register */
 	unsigned int	     rx_flags;      /* Throttling flags */
 	struct async_icount  icount;
-	wait_queue_head_t    msr_wait;	/* for handling sleeping while waiting
-						for msr change to happen */
 };
 
 #define THROTTLED		0x01
@@ -409,7 +407,6 @@ static int mct_u232_port_probe(struct us
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->msr_wait);
 
 	usb_set_serial_port_data(port, priv);
 
@@ -499,19 +496,15 @@ static void mct_u232_dtr_rts(struct usb_
 	unsigned int control_state;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected) {
-		/* drop DTR and RTS */
-		spin_lock_irq(&priv->lock);
-		if (on)
-			priv->control_state |= TIOCM_DTR | TIOCM_RTS;
-		else
-			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-		control_state = priv->control_state;
-		spin_unlock_irq(&priv->lock);
-		mct_u232_set_modem_ctrl(port, control_state);
-	}
-	mutex_unlock(&port->serial->disc_mutex);
+	spin_lock_irq(&priv->lock);
+	if (on)
+		priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+	else
+		priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+	control_state = priv->control_state;
+	spin_unlock_irq(&priv->lock);
+
+	mct_u232_set_modem_ctrl(port, control_state);
 }
 
 static void mct_u232_close(struct usb_serial_port *port)
@@ -610,7 +603,7 @@ static void mct_u232_read_int_callback(s
 		tty_kref_put(tty);
 	}
 #endif
-	wake_up_interruptible(&priv->msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -819,13 +812,17 @@ static int  mct_u232_ioctl(struct tty_st
 		cprev = mct_u232_port->icount;
 		spin_unlock_irqrestore(&mct_u232_port->lock, flags);
 		for ( ; ; ) {
-			prepare_to_wait(&mct_u232_port->msr_wait,
+			prepare_to_wait(&port->delta_msr_wait,
 					&wait, TASK_INTERRUPTIBLE);
 			schedule();
-			finish_wait(&mct_u232_port->msr_wait, &wait);
+			finish_wait(&port->delta_msr_wait, &wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			spin_lock_irqsave(&mct_u232_port->lock, flags);
 			cnow = mct_u232_port->icount;
 			spin_unlock_irqrestore(&mct_u232_port->lock, flags);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/mos7840.c linux-libre-3.8.13-gnu1/drivers/usb/serial/mos7840.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/mos7840.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/mos7840.c	2013-05-11 16:57:46.000000000 -0400
@@ -219,7 +219,6 @@ struct moschip_port {
 	char open;
 	char open_ports;
 	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
-	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */
 	int delta_msr_cond;
 	struct async_icount icount;
 	struct usb_serial_port *port;	/* loop back to the owner of this object */
@@ -423,6 +422,9 @@ static void mos7840_handle_new_msr(struc
 			icount->rng++;
 			smp_wmb();
 		}
+
+		mos7840_port->delta_msr_cond = 1;
+		wake_up_interruptible(&port->port->delta_msr_wait);
 	}
 }
 
@@ -1131,7 +1133,6 @@ static int mos7840_open(struct tty_struc
 
 	/* initialize our wait queues */
 	init_waitqueue_head(&mos7840_port->wait_chase);
-	init_waitqueue_head(&mos7840_port->delta_msr_wait);
 
 	/* initialize our icount structure */
 	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
@@ -2021,8 +2022,6 @@ static void mos7840_change_port_settings
 			mos7840_port->read_urb_busy = false;
 		}
 	}
-	wake_up(&mos7840_port->delta_msr_wait);
-	mos7840_port->delta_msr_cond = 1;
 	dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,
 		mos7840_port->shadowLCR);
 }
@@ -2223,13 +2222,18 @@ static int mos7840_ioctl(struct tty_stru
 		while (1) {
 			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
 			mos7840_port->delta_msr_cond = 0;
-			wait_event_interruptible(mos7840_port->delta_msr_wait,
-						 (mos7840_port->
+			wait_event_interruptible(port->delta_msr_wait,
+						 (port->serial->disconnected ||
+						  mos7840_port->
 						  delta_msr_cond == 1));
 
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = mos7840_port->icount;
 			smp_rmb();
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/option.c linux-libre-3.8.13-gnu1/drivers/usb/serial/option.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/option.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/option.c	2013-05-11 16:57:46.000000000 -0400
@@ -341,10 +341,13 @@ static void option_instat_callback(struc
 #define CINTERION_PRODUCT_EU3_E			0x0051
 #define CINTERION_PRODUCT_EU3_P			0x0052
 #define CINTERION_PRODUCT_PH8			0x0053
+#define CINTERION_PRODUCT_AH6			0x0055
+#define CINTERION_PRODUCT_PLS8			0x0060
 
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID			0x0b3c
 #define OLIVETTI_PRODUCT_OLICARD100		0xc000
+#define OLIVETTI_PRODUCT_OLICARD145		0xc003
 
 /* Celot products */
 #define CELOT_VENDOR_ID				0x211f
@@ -479,6 +482,7 @@ static const struct option_blacklist_inf
 
 static const struct option_blacklist_info alcatel_x200_blacklist = {
 	.sendsetup = BIT(0) | BIT(1),
+	.reserved = BIT(4),
 };
 
 static const struct option_blacklist_info zte_0037_blacklist = {
@@ -575,8 +579,15 @@ static const struct usb_device_id option
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
+	{ USB_DEVICE(QUANTA_VENDOR_ID, 0xea42),
+		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
@@ -1215,7 +1226,14 @@ static const struct usb_device_id option
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
 	  .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
 	},
-	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
+	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D),
+	  .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+	{ USB_DEVICE(ALCATEL_VENDOR_ID, 0x0052),
+	  .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+	{ USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b6),
+	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+	{ USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7),
+	  .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
@@ -1246,6 +1264,8 @@ static const struct usb_device_id option
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
@@ -1254,6 +1274,7 @@ static const struct usb_device_id option
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
 
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
 	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
 	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
 	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
@@ -1331,6 +1352,12 @@ static const struct usb_device_id option
 	{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },	/* D-Link DWM-156 (variant) */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },	/* D-Link DWM-156 (variant) */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/oti6858.c linux-libre-3.8.13-gnu1/drivers/usb/serial/oti6858.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/oti6858.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/oti6858.c	2013-05-11 16:57:46.000000000 -0400
@@ -188,7 +188,6 @@ struct oti6858_private {
 	u8 setup_done;
 	struct delayed_work delayed_setup_work;
 
-	wait_queue_head_t intr_wait;
 	struct usb_serial_port *port;   /* USB port with which associated */
 };
 
@@ -339,7 +338,6 @@ static int oti6858_port_probe(struct usb
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->intr_wait);
 	priv->port = port;
 	INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
 	INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
@@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		wait_event_interruptible(priv->intr_wait,
+		wait_event_interruptible(port->delta_msr_wait,
+					port->serial->disconnected ||
 					priv->status.pin_state != prev);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->status.pin_state & PIN_MASK;
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -763,7 +765,7 @@ static void oti6858_read_int_callback(st
 
 		if (!priv->transient) {
 			if (xs->pin_state != priv->status.pin_state)
-				wake_up_interruptible(&priv->intr_wait);
+				wake_up_interruptible(&port->delta_msr_wait);
 			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
 		}
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/pl2303.c linux-libre-3.8.13-gnu1/drivers/usb/serial/pl2303.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/pl2303.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/pl2303.c	2013-05-11 16:57:46.000000000 -0400
@@ -139,7 +139,6 @@ struct pl2303_serial_private {
 
 struct pl2303_private {
 	spinlock_t lock;
-	wait_queue_head_t delta_msr_wait;
 	u8 line_control;
 	u8 line_status;
 };
@@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	usb_set_serial_port_data(port, priv);
 
@@ -607,11 +605,14 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -719,7 +720,7 @@ static void pl2303_update_line_status(st
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (priv->line_status & UART_BREAK_ERROR)
 		usb_serial_handle_break(port);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	tty = tty_port_tty_get(&port->port);
 	if (!tty)
@@ -784,7 +785,7 @@ static void pl2303_process_read_urb(stru
 	line_status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/qcaux.c linux-libre-3.8.13-gnu1/drivers/usb/serial/qcaux.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/qcaux.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/qcaux.c	2013-05-11 16:57:46.000000000 -0400
@@ -69,6 +69,7 @@ static struct usb_device_id id_table[] =
 	{ 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 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/qcserial.c linux-libre-3.8.13-gnu1/drivers/usb/serial/qcserial.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/qcserial.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/qcserial.c	2013-05-11 16:57:46.000000000 -0400
@@ -197,12 +197,15 @@ static int qcprobe(struct usb_serial *se
 
 	if (is_gobi1k) {
 		/* Gobi 1K USB layout:
-		 * 0: serial port (doesn't respond)
+		 * 0: DM/DIAG (use libqcdm from ModemManager for communication)
 		 * 1: serial port (doesn't respond)
 		 * 2: AT-capable modem port
 		 * 3: QMI/net
 		 */
-		if (ifnum == 2)
+		if (ifnum == 0) {
+			dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n");
+			altsetting = 1;
+		} else if (ifnum == 2)
 			dev_dbg(dev, "Modem port found\n");
 		else
 			altsetting = -1;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/quatech2.c linux-libre-3.8.13-gnu1/drivers/usb/serial/quatech2.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/quatech2.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/quatech2.c	2013-05-11 16:57:46.000000000 -0400
@@ -128,7 +128,6 @@ struct qt2_port_private {
 	u8          shadowLSR;
 	u8          shadowMSR;
 
-	wait_queue_head_t   delta_msr_wait; /* Used for TIOCMIWAIT */
 	struct async_icount icount;
 
 	struct usb_serial_port *port;
@@ -506,8 +505,9 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		wait_event_interruptible(priv->delta_msr_wait,
-					 ((priv->icount.rng != prev.rng) ||
+		wait_event_interruptible(port->delta_msr_wait,
+					 (port->serial->disconnected ||
+					  (priv->icount.rng != prev.rng) ||
 					  (priv->icount.dsr != prev.dsr) ||
 					  (priv->icount.dcd != prev.dcd) ||
 					  (priv->icount.cts != prev.cts)));
@@ -515,6 +515,9 @@ static int wait_modem_info(struct usb_se
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		cur = priv->icount;
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -841,7 +844,6 @@ static int qt2_port_probe(struct usb_ser
 
 	spin_lock_init(&port_priv->lock);
 	spin_lock_init(&port_priv->urb_lock);
-	init_waitqueue_head(&port_priv->delta_msr_wait);
 	port_priv->port = port;
 
 	port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -945,19 +947,17 @@ static void qt2_dtr_rts(struct usb_seria
 	struct usb_device *dev = port->serial->dev;
 	struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected) {
-		/* Disable flow control */
-		if (!on && qt2_setregister(dev, port_priv->device_port,
+	/* Disable flow control */
+	if (!on) {
+		if (qt2_setregister(dev, port_priv->device_port,
 					   UART_MCR, 0) < 0)
 			dev_warn(&port->dev, "error from flowcontrol urb\n");
-		/* drop RTS and DTR */
-		if (on)
-			update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
-		else
-			update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
 	}
-	mutex_unlock(&port->serial->disc_mutex);
+	/* drop RTS and DTR */
+	if (on)
+		update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
+	else
+		update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
 }
 
 static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
@@ -986,7 +986,7 @@ static void qt2_update_msr(struct usb_se
 		if (newMSR & UART_MSR_TERI)
 			port_priv->icount.rng++;
 
-		wake_up_interruptible(&port_priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/sierra.c linux-libre-3.8.13-gnu1/drivers/usb/serial/sierra.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/sierra.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/sierra.c	2013-05-11 16:57:46.000000000 -0400
@@ -861,19 +861,13 @@ static int sierra_open(struct tty_struct
 
 static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 {
-	struct usb_serial *serial = port->serial;
 	struct sierra_port_private *portdata;
 
 	portdata = usb_get_serial_port_data(port);
 	portdata->rts_state = on;
 	portdata->dtr_state = on;
 
-	if (serial->dev) {
-		mutex_lock(&serial->disc_mutex);
-		if (!serial->disconnected)
-			sierra_send_setup(port);
-		mutex_unlock(&serial->disc_mutex);
-	}
+	sierra_send_setup(port);
 }
 
 static int sierra_startup(struct usb_serial *serial)
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/spcp8x5.c linux-libre-3.8.13-gnu1/drivers/usb/serial/spcp8x5.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/spcp8x5.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/spcp8x5.c	2013-05-11 16:57:46.000000000 -0400
@@ -149,7 +149,6 @@ enum spcp8x5_type {
 struct spcp8x5_private {
 	spinlock_t 	lock;
 	enum spcp8x5_type	type;
-	wait_queue_head_t	delta_msr_wait;
 	u8 			line_control;
 	u8 			line_status;
 };
@@ -179,7 +178,6 @@ static int spcp8x5_port_probe(struct usb
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 	priv->type = type;
 
 	usb_set_serial_port_data(port , priv);
@@ -476,7 +474,7 @@ static void spcp8x5_process_read_urb(str
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	/* wake up the wait for termios */
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
@@ -526,12 +524,15 @@ static int spcp8x5_wait_modem_info(struc
 
 	while (1) {
 		/* wake up in bulk read */
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		spin_unlock_irqrestore(&priv->lock, flags);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/ssu100.c linux-libre-3.8.13-gnu1/drivers/usb/serial/ssu100.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/ssu100.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/ssu100.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,7 +61,6 @@ struct ssu100_port_private {
 	spinlock_t status_lock;
 	u8 shadowLSR;
 	u8 shadowMSR;
-	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	struct async_icount icount;
 };
 
@@ -355,8 +354,9 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->status_lock, flags);
 
 	while (1) {
-		wait_event_interruptible(priv->delta_msr_wait,
-					 ((priv->icount.rng != prev.rng) ||
+		wait_event_interruptible(port->delta_msr_wait,
+					 (port->serial->disconnected ||
+					  (priv->icount.rng != prev.rng) ||
 					  (priv->icount.dsr != prev.dsr) ||
 					  (priv->icount.dcd != prev.dcd) ||
 					  (priv->icount.cts != prev.cts)));
@@ -364,6 +364,9 @@ static int wait_modem_info(struct usb_se
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->status_lock, flags);
 		cur = priv->icount;
 		spin_unlock_irqrestore(&priv->status_lock, flags);
@@ -445,7 +448,6 @@ static int ssu100_port_probe(struct usb_
 		return -ENOMEM;
 
 	spin_lock_init(&priv->status_lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	usb_set_serial_port_data(port, priv);
 
@@ -506,19 +508,16 @@ static void ssu100_dtr_rts(struct usb_se
 {
 	struct usb_device *dev = port->serial->dev;
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected) {
-		/* Disable flow control */
-		if (!on &&
-		    ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
+	/* Disable flow control */
+	if (!on) {
+		if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
 			dev_err(&port->dev, "error from flowcontrol urb\n");
-		/* drop RTS and DTR */
-		if (on)
-			set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
-		else
-			clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
 	}
-	mutex_unlock(&port->serial->disc_mutex);
+	/* drop RTS and DTR */
+	if (on)
+		set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
+	else
+		clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
 }
 
 static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
@@ -540,7 +539,7 @@ static void ssu100_update_msr(struct usb
 			priv->icount.dcd++;
 		if (msr & UART_MSR_TERI)
 			priv->icount.rng++;
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/ti_usb_3410_5052.c linux-libre-3.8.13-gnu1/drivers/usb/serial/ti_usb_3410_5052.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2013-05-01 16:48:44.000000000 -0400
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2013-05-11 19:24:32.000000000 -0400
@@ -74,7 +74,6 @@ struct ti_port {
 	int			tp_flags;
 	int			tp_closing_wait;/* in .01 secs */
 	struct async_icount	tp_icount;
-	wait_queue_head_t	tp_msr_wait;	/* wait for msr change */
 	wait_queue_head_t	tp_write_wait;
 	struct ti_device	*tp_tdev;
 	struct usb_serial_port	*tp_port;
@@ -426,7 +425,6 @@ static int ti_port_probe(struct usb_seri
 	else
 		tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
 	tport->tp_closing_wait = closing_wait;
-	init_waitqueue_head(&tport->tp_msr_wait);
 	init_waitqueue_head(&tport->tp_write_wait);
 	if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
 		kfree(tport);
@@ -778,9 +776,13 @@ static int ti_ioctl(struct tty_struct *t
 		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
 		cprev = tport->tp_icount;
 		while (1) {
-			interruptible_sleep_on(&tport->tp_msr_wait);
+			interruptible_sleep_on(&port->delta_msr_wait);
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = tport->tp_icount;
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -1394,7 +1396,7 @@ static void ti_handle_new_msr(struct ti_
 			icount->dcd++;
 		if (msr & TI_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&tport->tp_msr_wait);
+		wake_up_interruptible(&tport->tp_port->delta_msr_wait);
 		spin_unlock_irqrestore(&tport->tp_lock, flags);
 	}
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/usb-serial.c linux-libre-3.8.13-gnu1/drivers/usb/serial/usb-serial.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/usb-serial.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/usb-serial.c	2013-05-11 16:57:46.000000000 -0400
@@ -151,6 +151,7 @@ static void destroy_serial(struct kref *
 		}
 	}
 
+	usb_put_intf(serial->interface);
 	usb_put_dev(serial->dev);
 	kfree(serial);
 }
@@ -614,7 +615,7 @@ static struct usb_serial *create_serial(
 	}
 	serial->dev = usb_get_dev(dev);
 	serial->type = driver;
-	serial->interface = interface;
+	serial->interface = usb_get_intf(interface);
 	kref_init(&serial->kref);
 	mutex_init(&serial->disc_mutex);
 	serial->minor = SERIAL_TTY_NO_MINOR;
@@ -688,10 +689,20 @@ static int serial_carrier_raised(struct
 static void serial_dtr_rts(struct tty_port *port, int on)
 {
 	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
-	struct usb_serial_driver *drv = p->serial->type;
+	struct usb_serial *serial = p->serial;
+	struct usb_serial_driver *drv = serial->type;
 
-	if (drv->dtr_rts)
+	if (!drv->dtr_rts)
+		return;
+	/*
+	 * Work-around bug in the tty-layer which can result in dtr_rts
+	 * being called after a disconnect (and tty_unregister_device
+	 * has returned). Remove once bug has been squashed.
+	 */
+	mutex_lock(&serial->disc_mutex);
+	if (!serial->disconnected)
 		drv->dtr_rts(p, on);
+	mutex_unlock(&serial->disc_mutex);
 }
 
 static const struct tty_port_operations serial_port_ops = {
@@ -886,6 +897,7 @@ static int usb_serial_probe(struct usb_i
 		port->port.ops = &serial_port_ops;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
+		init_waitqueue_head(&port->delta_msr_wait);
 		/* Keep this for private driver use for the moment but
 		   should probably go away */
 		INIT_WORK(&port->work, usb_serial_port_work);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/serial/usb_wwan.c linux-libre-3.8.13-gnu1/drivers/usb/serial/usb_wwan.c
--- linux-libre-3.8-gnu1/drivers/usb/serial/usb_wwan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/serial/usb_wwan.c	2013-05-11 16:57:46.000000000 -0400
@@ -38,7 +38,6 @@
 
 void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
 {
-	struct usb_serial *serial = port->serial;
 	struct usb_wwan_port_private *portdata;
 	struct usb_wwan_intf_private *intfdata;
 
@@ -48,12 +47,11 @@ void usb_wwan_dtr_rts(struct usb_serial_
 		return;
 
 	portdata = usb_get_serial_port_data(port);
-	mutex_lock(&serial->disc_mutex);
+	/* FIXME: locking */
 	portdata->rts_state = on;
 	portdata->dtr_state = on;
-	if (serial->dev)
-		intfdata->send_setup(port);
-	mutex_unlock(&serial->disc_mutex);
+
+	intfdata->send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_dtr_rts);
 
diff -druNp linux-libre-3.8-gnu1/drivers/usb/storage/cypress_atacb.c linux-libre-3.8.13-gnu1/drivers/usb/storage/cypress_atacb.c
--- linux-libre-3.8-gnu1/drivers/usb/storage/cypress_atacb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/storage/cypress_atacb.c	2013-05-11 16:57:46.000000000 -0400
@@ -248,14 +248,26 @@ static int cypress_probe(struct usb_inte
 {
 	struct us_data *us;
 	int result;
+	struct usb_device *device;
 
 	result = usb_stor_probe1(&us, intf, id,
 			(id - cypress_usb_ids) + cypress_unusual_dev_list);
 	if (result)
 		return result;
 
-	us->protocol_name = "Transparent SCSI with Cypress ATACB";
-	us->proto_handler = cypress_atacb_passthrough;
+	/* Among CY7C68300 chips, the A revision does not support Cypress ATACB
+	 * Filter out this revision from EEPROM default descriptor values
+	 */
+	device = interface_to_usbdev(intf);
+	if (device->descriptor.iManufacturer != 0x38 ||
+	    device->descriptor.iProduct != 0x4e ||
+	    device->descriptor.iSerialNumber != 0x64) {
+		us->protocol_name = "Transparent SCSI with Cypress ATACB";
+		us->proto_handler = cypress_atacb_passthrough;
+	} else {
+		us->protocol_name = "Transparent SCSI";
+		us->proto_handler = usb_stor_transparent_scsi_command;
+	}
 
 	result = usb_stor_probe2(us);
 	return result;
diff -druNp linux-libre-3.8-gnu1/drivers/usb/storage/initializers.c linux-libre-3.8.13-gnu1/drivers/usb/storage/initializers.c
--- linux-libre-3.8-gnu1/drivers/usb/storage/initializers.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/storage/initializers.c	2013-05-11 16:57:46.000000000 -0400
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_dat
 	return 0;
 }
 
-/* This places the HUAWEI usb dongles in multi-port mode */
-static int usb_stor_huawei_feature_init(struct us_data *us)
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us)
 {
 	int result;
 
@@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(
 	US_DEBUGP("Huawei mode set result is %d\n", result);
 	return 0;
 }
-
-/*
- * It will send a scsi switch command called rewind' to huawei dongle.
- * When the dongle receives this command at the first time,
- * it will reboot immediately. After rebooted, it will ignore this command.
- * So it is  unnecessary to read its response.
- */
-static int usb_stor_huawei_scsi_init(struct us_data *us)
-{
-	int result = 0;
-	int act_len = 0;
-	struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
-	char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
-			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-	bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcbw->Tag = 0;
-	bcbw->DataTransferLength = 0;
-	bcbw->Flags = bcbw->Lun = 0;
-	bcbw->Length = sizeof(rewind_cmd);
-	memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
-	memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
-
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
-					US_BULK_CB_WRAP_LEN, &act_len);
-	US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
-	return result;
-}
-
-/*
- * It tries to find the supported Huawei USB dongles.
- * In Huawei, they assign the following product IDs
- * for all of their mobile broadband dongles,
- * including the new dongles in the future.
- * So if the product ID is not included in this list,
- * it means it is not Huawei's mobile broadband dongles.
- */
-static int usb_stor_huawei_dongles_pid(struct us_data *us)
-{
-	struct usb_interface_descriptor *idesc;
-	int idProduct;
-
-	idesc = &us->pusb_intf->cur_altsetting->desc;
-	idProduct = us->pusb_dev->descriptor.idProduct;
-	/* The first port is CDROM,
-	 * means the dongle in the single port mode,
-	 * and a switch command is required to be sent. */
-	if (idesc && idesc->bInterfaceNumber == 0) {
-		if ((idProduct == 0x1001)
-			|| (idProduct == 0x1003)
-			|| (idProduct == 0x1004)
-			|| (idProduct >= 0x1401 && idProduct <= 0x1500)
-			|| (idProduct >= 0x1505 && idProduct <= 0x1600)
-			|| (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-int usb_stor_huawei_init(struct us_data *us)
-{
-	int result = 0;
-
-	if (usb_stor_huawei_dongles_pid(us)) {
-		if (us->pusb_dev->descriptor.idProduct >= 0x1446)
-			result = usb_stor_huawei_scsi_init(us);
-		else
-			result = usb_stor_huawei_feature_init(us);
-	}
-	return result;
-}
diff -druNp linux-libre-3.8-gnu1/drivers/usb/storage/initializers.h linux-libre-3.8.13-gnu1/drivers/usb/storage/initializers.h
--- linux-libre-3.8-gnu1/drivers/usb/storage/initializers.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/storage/initializers.h	2013-05-11 16:57:46.000000000 -0400
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
 
-/* This places the HUAWEI usb dongles in multi-port mode */
-int usb_stor_huawei_init(struct us_data *us);
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us);
diff -druNp linux-libre-3.8-gnu1/drivers/usb/storage/unusual_cypress.h linux-libre-3.8.13-gnu1/drivers/usb/storage/unusual_cypress.h
--- linux-libre-3.8-gnu1/drivers/usb/storage/unusual_cypress.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/storage/unusual_cypress.h	2013-05-11 16:57:46.000000000 -0400
@@ -31,7 +31,7 @@ UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x
 		"Cypress ISD-300LP",
 		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
 
-UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999,
+UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219,
 		"Super Top",
 		"USB 2.0  SATA BRIDGE",
 		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
diff -druNp linux-libre-3.8-gnu1/drivers/usb/storage/unusual_devs.h linux-libre-3.8.13-gnu1/drivers/usb/storage/unusual_devs.h
--- linux-libre-3.8-gnu1/drivers/usb/storage/unusual_devs.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/usb/storage/unusual_devs.h	2013-05-11 16:57:46.000000000 -0400
@@ -488,6 +488,13 @@ UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
 
+/* Added by Dmitry Artamonow <mad_soft@inbox.ru> */
+UNUSUAL_DEV(  0x04e8, 0x5136, 0x0000, 0x9999,
+		"Samsung",
+		"YP-Z3",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_MAX_SECTORS_64),
+
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
  * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
  * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
@@ -1527,10 +1534,335 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x
 /* Reported by fangxiaozhi <huananhu@huawei.com>
  * This brings the HUAWEI data card devices into multi-port mode
  */
-UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
+UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+		0),
+UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
+		"HUAWEI MOBILE",
+		"Mass Storage",
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
diff -druNp linux-libre-3.8-gnu1/drivers/vfio/pci/vfio_pci.c linux-libre-3.8.13-gnu1/drivers/vfio/pci/vfio_pci.c
--- linux-libre-3.8-gnu1/drivers/vfio/pci/vfio_pci.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/vfio/pci/vfio_pci.c	2013-05-11 16:57:46.000000000 -0400
@@ -331,6 +331,7 @@ static long vfio_pci_ioctl(void *device_
 
 		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
 			size_t size;
+			int max = vfio_pci_get_irq_count(vdev, hdr.index);
 
 			if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
 				size = sizeof(uint8_t);
@@ -340,7 +341,7 @@ static long vfio_pci_ioctl(void *device_
 				return -EINVAL;
 
 			if (hdr.argsz - minsz < hdr.count * size ||
-			    hdr.count > vfio_pci_get_irq_count(vdev, hdr.index))
+			    hdr.start >= max || hdr.start + hdr.count > max)
 				return -EINVAL;
 
 			data = memdup_user((void __user *)(arg + minsz),
diff -druNp linux-libre-3.8-gnu1/drivers/vhost/net.c linux-libre-3.8.13-gnu1/drivers/vhost/net.c
--- linux-libre-3.8-gnu1/drivers/vhost/net.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/vhost/net.c	2013-05-11 16:57:46.000000000 -0400
@@ -339,7 +339,8 @@ static void handle_tx(struct vhost_net *
 				msg.msg_controllen = 0;
 				ubufs = NULL;
 			} else {
-				struct ubuf_info *ubuf = &vq->ubuf_info[head];
+				struct ubuf_info *ubuf;
+				ubuf = vq->ubuf_info + vq->upend_idx;
 
 				vq->heads[vq->upend_idx].len =
 					VHOST_DMA_IN_PROGRESS;
diff -druNp linux-libre-3.8-gnu1/drivers/video/atmel_lcdfb.c linux-libre-3.8.13-gnu1/drivers/video/atmel_lcdfb.c
--- linux-libre-3.8-gnu1/drivers/video/atmel_lcdfb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/atmel_lcdfb.c	2013-05-11 16:57:46.000000000 -0400
@@ -422,17 +422,22 @@ static int atmel_lcdfb_check_var(struct
 			= var->bits_per_pixel;
 		break;
 	case 16:
+		/* Older SOCs use IBGR:555 rather than BGR:565. */
+		if (sinfo->have_intensity_bit)
+			var->green.length = 5;
+		else
+			var->green.length = 6;
+
 		if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-			/* RGB:565 mode */
-			var->red.offset = 11;
+			/* RGB:5X5 mode */
+			var->red.offset = var->green.length + 5;
 			var->blue.offset = 0;
 		} else {
-			/* BGR:565 mode */
+			/* BGR:5X5 mode */
 			var->red.offset = 0;
-			var->blue.offset = 11;
+			var->blue.offset = var->green.length + 5;
 		}
 		var->green.offset = 5;
-		var->green.length = 6;
 		var->red.length = var->blue.length = 5;
 		break;
 	case 32:
@@ -679,8 +684,7 @@ static int atmel_lcdfb_setcolreg(unsigne
 
 	case FB_VISUAL_PSEUDOCOLOR:
 		if (regno < 256) {
-			if (cpu_is_at91sam9261() || cpu_is_at91sam9263()
-			    || cpu_is_at91sam9rl()) {
+			if (sinfo->have_intensity_bit) {
 				/* old style I+BGR:555 */
 				val  = ((red   >> 11) & 0x001f);
 				val |= ((green >>  6) & 0x03e0);
@@ -870,6 +874,10 @@ static int __init atmel_lcdfb_probe(stru
 	}
 	sinfo->info = info;
 	sinfo->pdev = pdev;
+	if (cpu_is_at91sam9261() || cpu_is_at91sam9263() ||
+							cpu_is_at91sam9rl()) {
+		sinfo->have_intensity_bit = true;
+	}
 
 	strcpy(info->fix.id, sinfo->pdev->name);
 	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
diff -druNp linux-libre-3.8-gnu1/drivers/video/backlight/adp8860_bl.c linux-libre-3.8.13-gnu1/drivers/video/backlight/adp8860_bl.c
--- linux-libre-3.8-gnu1/drivers/video/backlight/adp8860_bl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/backlight/adp8860_bl.c	2013-05-11 16:57:46.000000000 -0400
@@ -783,7 +783,7 @@ static int adp8860_i2c_suspend(struct i2
 
 static int adp8860_i2c_resume(struct i2c_client *client)
 {
-	adp8860_set_bits(client, ADP8860_MDCR, NSTBY);
+	adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN);
 
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/video/backlight/adp8870_bl.c linux-libre-3.8.13-gnu1/drivers/video/backlight/adp8870_bl.c
--- linux-libre-3.8-gnu1/drivers/video/backlight/adp8870_bl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/backlight/adp8870_bl.c	2013-05-11 16:57:46.000000000 -0400
@@ -957,7 +957,7 @@ static int adp8870_i2c_suspend(struct i2
 
 static int adp8870_i2c_resume(struct i2c_client *client)
 {
-	adp8870_set_bits(client, ADP8870_MDCR, NSTBY);
+	adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN);
 
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/video/console/fbcon.c linux-libre-3.8.13-gnu1/drivers/video/console/fbcon.c
--- linux-libre-3.8-gnu1/drivers/video/console/fbcon.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/console/fbcon.c	2013-05-11 16:57:46.000000000 -0400
@@ -529,6 +529,33 @@ static int search_for_mapped_con(void)
 	return retval;
 }
 
+static int do_fbcon_takeover(int show_logo)
+{
+	int err, i;
+
+	if (!num_registered_fb)
+		return -ENODEV;
+
+	if (!show_logo)
+		logo_shown = FBCON_LOGO_DONTSHOW;
+
+	for (i = first_fb_vc; i <= last_fb_vc; i++)
+		con2fb_map[i] = info_idx;
+
+	err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
+				fbcon_is_default);
+
+	if (err) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++)
+			con2fb_map[i] = -1;
+		info_idx = -1;
+	} else {
+		fbcon_has_console_bind = 1;
+	}
+
+	return err;
+}
+
 static int fbcon_takeover(int show_logo)
 {
 	int err, i;
@@ -815,6 +842,8 @@ static void con2fb_init_display(struct v
  *
  *	Maps a virtual console @unit to a frame buffer device
  *	@newidx.
+ *
+ *	This should be called with the console lock held.
  */
 static int set_con2fb_map(int unit, int newidx, int user)
 {
@@ -832,7 +861,7 @@ static int set_con2fb_map(int unit, int
 
 	if (!search_for_mapped_con() || !con_is_bound(&fb_con)) {
 		info_idx = newidx;
-		return fbcon_takeover(0);
+		return do_fbcon_takeover(0);
 	}
 
 	if (oldidx != -1)
@@ -840,7 +869,6 @@ static int set_con2fb_map(int unit, int
 
 	found = search_fb_in_map(newidx);
 
-	console_lock();
 	con2fb_map[unit] = newidx;
 	if (!err && !found)
  		err = con2fb_acquire_newinfo(vc, info, unit, oldidx);
@@ -867,7 +895,6 @@ static int set_con2fb_map(int unit, int
 	if (!search_fb_in_map(info_idx))
 		info_idx = newidx;
 
-	console_unlock();
  	return err;
 }
 
@@ -990,7 +1017,7 @@ static const char *fbcon_startup(void)
 	}
 
 	/* Setup default font */
-	if (!p->fontdata) {
+	if (!p->fontdata && !vc->vc_font.data) {
 		if (!fontname[0] || !(font = find_font(fontname)))
 			font = get_default_font(info->var.xres,
 						info->var.yres,
@@ -1000,6 +1027,8 @@ static const char *fbcon_startup(void)
 		vc->vc_font.height = font->height;
 		vc->vc_font.data = (void *)(p->fontdata = font->data);
 		vc->vc_font.charcount = 256; /* FIXME  Need to support more fonts */
+	} else {
+		p->fontdata = vc->vc_font.data;
 	}
 
 	cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
@@ -1159,9 +1188,9 @@ static void fbcon_init(struct vc_data *v
 	ops->p = &fb_display[fg_console];
 }
 
-static void fbcon_free_font(struct display *p)
+static void fbcon_free_font(struct display *p, bool freefont)
 {
-	if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
+	if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
 		kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
 	p->fontdata = NULL;
 	p->userfont = 0;
@@ -1173,8 +1202,8 @@ static void fbcon_deinit(struct vc_data
 	struct fb_info *info;
 	struct fbcon_ops *ops;
 	int idx;
+	bool free_font = true;
 
-	fbcon_free_font(p);
 	idx = con2fb_map[vc->vc_num];
 
 	if (idx == -1)
@@ -1185,6 +1214,8 @@ static void fbcon_deinit(struct vc_data
 	if (!info)
 		goto finished;
 
+	if (info->flags & FBINFO_MISC_FIRMWARE)
+		free_font = false;
 	ops = info->fbcon_par;
 
 	if (!ops)
@@ -1196,6 +1227,10 @@ static void fbcon_deinit(struct vc_data
 	ops->flags &= ~FBCON_FLAGS_INIT;
 finished:
 
+	fbcon_free_font(p, free_font);
+	if (free_font)
+		vc->vc_font.data = NULL;
+
 	if (!con_is_bound(&fb_con))
 		fbcon_exit();
 
@@ -2977,7 +3012,7 @@ static int fbcon_unbind(void)
 {
 	int ret;
 
-	ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
+	ret = do_unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
 				fbcon_is_default);
 
 	if (!ret)
@@ -2992,6 +3027,7 @@ static inline int fbcon_unbind(void)
 }
 #endif /* CONFIG_VT_HW_CONSOLE_BINDING */
 
+/* called with console_lock held */
 static int fbcon_fb_unbind(int idx)
 {
 	int i, new_idx = -1, ret = 0;
@@ -3018,6 +3054,7 @@ static int fbcon_fb_unbind(int idx)
 	return ret;
 }
 
+/* called with console_lock held */
 static int fbcon_fb_unregistered(struct fb_info *info)
 {
 	int i, idx;
@@ -3050,11 +3087,12 @@ static int fbcon_fb_unregistered(struct
 		primary_device = -1;
 
 	if (!num_registered_fb)
-		unregister_con_driver(&fb_con);
+		do_unregister_con_driver(&fb_con);
 
 	return 0;
 }
 
+/* called with console_lock held */
 static void fbcon_remap_all(int idx)
 {
 	int i;
@@ -3099,6 +3137,7 @@ static inline void fbcon_select_primary(
 }
 #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
 
+/* called with console_lock held */
 static int fbcon_fb_registered(struct fb_info *info)
 {
 	int ret = 0, i, idx;
@@ -3115,7 +3154,7 @@ static int fbcon_fb_registered(struct fb
 		}
 
 		if (info_idx != -1)
-			ret = fbcon_takeover(1);
+			ret = do_fbcon_takeover(1);
 	} else {
 		for (i = first_fb_vc; i <= last_fb_vc; i++) {
 			if (con2fb_map_boot[i] == idx)
@@ -3251,6 +3290,7 @@ static int fbcon_event_notify(struct not
 		ret = fbcon_fb_unregistered(info);
 		break;
 	case FB_EVENT_SET_CONSOLE_MAP:
+		/* called with console lock held */
 		con2fb = event->data;
 		ret = set_con2fb_map(con2fb->console - 1,
 				     con2fb->framebuffer, 1);
diff -druNp linux-libre-3.8-gnu1/drivers/video/console/vgacon.c linux-libre-3.8.13-gnu1/drivers/video/console/vgacon.c
--- linux-libre-3.8-gnu1/drivers/video/console/vgacon.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/console/vgacon.c	2013-05-11 16:57:46.000000000 -0400
@@ -1064,7 +1064,7 @@ static int vgacon_do_font_op(struct vgas
 	unsigned short video_port_status = vga_video_port_reg + 6;
 	int font_select = 0x00, beg, i;
 	char *charmap;
-	
+	bool clear_attribs = false;
 	if (vga_video_type != VIDEO_TYPE_EGAM) {
 		charmap = (char *) VGA_MAP_MEM(colourmap, 0);
 		beg = 0x0e;
@@ -1169,12 +1169,6 @@ static int vgacon_do_font_op(struct vgas
 
 	/* if 512 char mode is already enabled don't re-enable it. */
 	if ((set) && (ch512 != vga_512_chars)) {
-		/* attribute controller */
-		for (i = 0; i < MAX_NR_CONSOLES; i++) {
-			struct vc_data *c = vc_cons[i].d;
-			if (c && c->vc_sw == &vga_con)
-				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
-		}
 		vga_512_chars = ch512;
 		/* 256-char: enable intensity bit
 		   512-char: disable intensity bit */
@@ -1185,8 +1179,22 @@ static int vgacon_do_font_op(struct vgas
 		   it means, but it works, and it appears necessary */
 		inb_p(video_port_status);
 		vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);	
+		clear_attribs = true;
 	}
 	raw_spin_unlock_irq(&vga_lock);
+
+	if (clear_attribs) {
+		for (i = 0; i < MAX_NR_CONSOLES; i++) {
+			struct vc_data *c = vc_cons[i].d;
+			if (c && c->vc_sw == &vga_con) {
+				/* force hi font mask to 0, so we always clear
+				   the bit on either transition */
+				c->vc_hi_font_mask = 0x00;
+				clear_buffer_attributes(c);
+				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+			}
+		}
+	}
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/video/ep93xx-fb.c linux-libre-3.8.13-gnu1/drivers/video/ep93xx-fb.c
--- linux-libre-3.8-gnu1/drivers/video/ep93xx-fb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/ep93xx-fb.c	2013-05-11 16:57:46.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/fb.h>
+#include <linux/io.h>
 
 #include <linux/platform_data/video-ep93xx.h>
 
diff -druNp linux-libre-3.8-gnu1/drivers/video/fbmem.c linux-libre-3.8.13-gnu1/drivers/video/fbmem.c
--- linux-libre-3.8-gnu1/drivers/video/fbmem.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/fbmem.c	2013-05-11 16:57:46.000000000 -0400
@@ -1177,8 +1177,10 @@ static long do_fb_ioctl(struct fb_info *
 		event.data = &con2fb;
 		if (!lock_fb_info(info))
 			return -ENODEV;
+		console_lock();
 		event.info = info;
 		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
+		console_unlock();
 		unlock_fb_info(info);
 		break;
 	case FBIOBLANK:
@@ -1371,15 +1373,12 @@ fb_mmap(struct file *file, struct vm_are
 {
 	struct fb_info *info = file_fb_info(file);
 	struct fb_ops *fb;
-	unsigned long off;
+	unsigned long mmio_pgoff;
 	unsigned long start;
 	u32 len;
 
 	if (!info)
 		return -ENODEV;
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-	off = vma->vm_pgoff << PAGE_SHIFT;
 	fb = info->fbops;
 	if (!fb)
 		return -ENODEV;
@@ -1391,32 +1390,24 @@ fb_mmap(struct file *file, struct vm_are
 		return res;
 	}
 
-	/* frame buffer memory */
+	/*
+	 * Ugh. This can be either the frame buffer mapping, or
+	 * if pgoff points past it, the mmio mapping.
+	 */
 	start = info->fix.smem_start;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
-	if (off >= len) {
-		/* memory mapped io */
-		off -= len;
-		if (info->var.accel_flags) {
-			mutex_unlock(&info->mm_lock);
-			return -EINVAL;
-		}
+	len = info->fix.smem_len;
+	mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+	if (vma->vm_pgoff >= mmio_pgoff) {
+		vma->vm_pgoff -= mmio_pgoff;
 		start = info->fix.mmio_start;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+		len = info->fix.mmio_len;
 	}
 	mutex_unlock(&info->mm_lock);
-	start &= PAGE_MASK;
-	if ((vma->vm_end - vma->vm_start + off) > len)
-		return -EINVAL;
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by io_remap_pfn_range()*/
+
 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-	fb_pgprotect(file, vma, off);
-	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
-		return -EAGAIN;
-	return 0;
+	fb_pgprotect(file, vma, start);
+
+	return vm_iomap_memory(vma, start, len);
 }
 
 static int
@@ -1650,7 +1641,9 @@ static int do_register_framebuffer(struc
 	event.info = fb_info;
 	if (!lock_fb_info(fb_info))
 		return -ENODEV;
+	console_lock();
 	fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+	console_unlock();
 	unlock_fb_info(fb_info);
 	return 0;
 }
@@ -1666,8 +1659,10 @@ static int do_unregister_framebuffer(str
 
 	if (!lock_fb_info(fb_info))
 		return -ENODEV;
+	console_lock();
 	event.info = fb_info;
 	ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+	console_unlock();
 	unlock_fb_info(fb_info);
 
 	if (ret)
@@ -1682,7 +1677,9 @@ static int do_unregister_framebuffer(str
 	num_registered_fb--;
 	fb_cleanup_device(fb_info);
 	event.info = fb_info;
+	console_lock();
 	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+	console_unlock();
 
 	/* this may free fb info */
 	put_fb_info(fb_info);
@@ -1853,11 +1850,8 @@ int fb_new_modelist(struct fb_info *info
 	err = 1;
 
 	if (!list_empty(&info->modelist)) {
-		if (!lock_fb_info(info))
-			return -ENODEV;
 		event.info = info;
 		err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
-		unlock_fb_info(info);
 	}
 
 	return err;
diff -druNp linux-libre-3.8-gnu1/drivers/video/fbsysfs.c linux-libre-3.8.13-gnu1/drivers/video/fbsysfs.c
--- linux-libre-3.8-gnu1/drivers/video/fbsysfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/fbsysfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -177,6 +177,8 @@ static ssize_t store_modes(struct device
 	if (i * sizeof(struct fb_videomode) != count)
 		return -EINVAL;
 
+	if (!lock_fb_info(fb_info))
+		return -ENODEV;
 	console_lock();
 	list_splice(&fb_info->modelist, &old_list);
 	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
@@ -188,6 +190,7 @@ static ssize_t store_modes(struct device
 		fb_destroy_modelist(&old_list);
 
 	console_unlock();
+	unlock_fb_info(fb_info);
 
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/drivers/video/fsl-diu-fb.c linux-libre-3.8.13-gnu1/drivers/video/fsl-diu-fb.c
--- linux-libre-3.8-gnu1/drivers/video/fsl-diu-fb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/video/fsl-diu-fb.c	2013-05-11 16:57:46.000000000 -0400
@@ -944,7 +944,7 @@ static u32 fsl_diu_get_pixel_format(unsi
 #define PF_COMP_0_MASK		0x0000000F
 #define PF_COMP_0_SHIFT		0
 
-#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \
+#define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \
 	cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
 	(blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
 	(red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
@@ -954,10 +954,10 @@ static u32 fsl_diu_get_pixel_format(unsi
 	switch (bits_per_pixel) {
 	case 32:
 		/* 0x88883316 */
-		return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8);
+		return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8);
 	case 24:
 		/* 0x88082219 */
-		return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8);
+		return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0);
 	case 16:
 		/* 0x65053118 */
 		return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
@@ -1232,6 +1232,16 @@ static int fsl_diu_ioctl(struct fb_info
 	return 0;
 }
 
+static inline void fsl_diu_enable_interrupts(struct fsl_diu_data *data)
+{
+	u32 int_mask = INT_UNDRUN; /* enable underrun detection */
+
+	if (IS_ENABLED(CONFIG_NOT_COHERENT_CACHE))
+		int_mask |= INT_VSYNC; /* enable vertical sync */
+
+	clrbits32(&data->diu_reg->int_mask, int_mask);
+}
+
 /* turn on fb if count == 1
  */
 static int fsl_diu_open(struct fb_info *info, int user)
@@ -1251,19 +1261,7 @@ static int fsl_diu_open(struct fb_info *
 		if (res < 0)
 			mfbi->count--;
 		else {
-			struct fsl_diu_data *data = mfbi->parent;
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-			/*
-			 * Enable underrun detection and vertical sync
-			 * interrupts.
-			 */
-			clrbits32(&data->diu_reg->int_mask,
-				  INT_UNDRUN | INT_VSYNC);
-#else
-			/* Enable underrun detection */
-			clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
-#endif
+			fsl_diu_enable_interrupts(mfbi->parent);
 			fsl_diu_enable_panel(info);
 		}
 	}
@@ -1283,9 +1281,18 @@ static int fsl_diu_release(struct fb_inf
 	mfbi->count--;
 	if (mfbi->count == 0) {
 		struct fsl_diu_data *data = mfbi->parent;
+		bool disable = true;
+		int i;
 
-		/* Disable interrupts */
-		out_be32(&data->diu_reg->int_mask, 0xffffffff);
+		/* Disable interrupts only if all AOIs are closed */
+		for (i = 0; i < NUM_AOIS; i++) {
+			struct mfb_info *mi = data->fsl_diu_info[i].par;
+
+			if (mi->count)
+				disable = false;
+		}
+		if (disable)
+			out_be32(&data->diu_reg->int_mask, 0xffffffff);
 		fsl_diu_disable_panel(info);
 	}
 
@@ -1614,14 +1621,6 @@ static int fsl_diu_probe(struct platform
 	out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
 	out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
 
-	for (i = 0; i < NUM_AOIS; i++) {
-		ret = install_fb(&data->fsl_diu_info[i]);
-		if (ret) {
-			dev_err(&pdev->dev, "could not register fb %d\n", i);
-			goto error;
-		}
-	}
-
 	/*
 	 * Older versions of U-Boot leave interrupts enabled, so disable
 	 * all of them and clear the status register.
@@ -1630,12 +1629,21 @@ static int fsl_diu_probe(struct platform
 	in_be32(&data->diu_reg->int_status);
 
 	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
-			  &data->diu_reg);
+			  data->diu_reg);
 	if (ret) {
 		dev_err(&pdev->dev, "could not claim irq\n");
 		goto error;
 	}
 
+	for (i = 0; i < NUM_AOIS; i++) {
+		ret = install_fb(&data->fsl_diu_info[i]);
+		if (ret) {
+			dev_err(&pdev->dev, "could not register fb %d\n", i);
+			free_irq(data->irq, data->diu_reg);
+			goto error;
+		}
+	}
+
 	sysfs_attr_init(&data->dev_attr.attr);
 	data->dev_attr.attr.name = "monitor";
 	data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
@@ -1667,7 +1675,7 @@ static int fsl_diu_remove(struct platfor
 	data = dev_get_drvdata(&pdev->dev);
 	disable_lcdc(&data->fsl_diu_info[0]);
 
-	free_irq(data->irq, &data->diu_reg);
+	free_irq(data->irq, data->diu_reg);
 
 	for (i = 0; i < NUM_AOIS; i++)
 		uninstall_fb(&data->fsl_diu_info[i]);
diff -druNp linux-libre-3.8-gnu1/drivers/w1/masters/w1-gpio.c linux-libre-3.8.13-gnu1/drivers/w1/masters/w1-gpio.c
--- linux-libre-3.8-gnu1/drivers/w1/masters/w1-gpio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/w1/masters/w1-gpio.c	2013-05-11 16:57:46.000000000 -0400
@@ -72,7 +72,7 @@ static int w1_gpio_probe_dt(struct platf
 	return 0;
 }
 
-static int __init w1_gpio_probe(struct platform_device *pdev)
+static int w1_gpio_probe(struct platform_device *pdev)
 {
 	struct w1_bus_master *master;
 	struct w1_gpio_platform_data *pdata;
@@ -158,7 +158,7 @@ static int __init w1_gpio_probe(struct p
 	return err;
 }
 
-static int __exit w1_gpio_remove(struct platform_device *pdev)
+static int w1_gpio_remove(struct platform_device *pdev)
 {
 	struct w1_bus_master *master = platform_get_drvdata(pdev);
 	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -210,7 +210,7 @@ static struct platform_driver w1_gpio_dr
 		.of_match_table = of_match_ptr(w1_gpio_dt_ids),
 	},
 	.probe = w1_gpio_probe,
-	.remove	= __exit_p(w1_gpio_remove),
+	.remove	= w1_gpio_remove,
 	.suspend = w1_gpio_suspend,
 	.resume = w1_gpio_resume,
 };
diff -druNp linux-libre-3.8-gnu1/drivers/w1/w1.c linux-libre-3.8.13-gnu1/drivers/w1/w1.c
--- linux-libre-3.8-gnu1/drivers/w1/w1.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/w1/w1.c	2013-05-11 16:57:46.000000000 -0400
@@ -924,7 +924,8 @@ void w1_search(struct w1_master *dev, u8
 			tmp64 = (triplet_ret >> 2);
 			rn |= (tmp64 << i);
 
-			if (kthread_should_stop()) {
+			/* ensure we're called from kthread and not by netlink callback */
+			if (!dev->priv && kthread_should_stop()) {
 				mutex_unlock(&dev->bus_mutex);
 				dev_dbg(&dev->dev, "Abort w1_search\n");
 				return;
diff -druNp linux-libre-3.8-gnu1/drivers/watchdog/Kconfig linux-libre-3.8.13-gnu1/drivers/watchdog/Kconfig
--- linux-libre-3.8-gnu1/drivers/watchdog/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/watchdog/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -79,6 +79,7 @@ config DA9052_WATCHDOG
 config DA9055_WATCHDOG
 	tristate "Dialog Semiconductor DA9055 Watchdog"
 	depends on MFD_DA9055
+	select WATCHDOG_CORE
 	help
 	  If you say yes here you get support for watchdog on the Dialog
 	  Semiconductor DA9055 PMIC.
diff -druNp linux-libre-3.8-gnu1/drivers/watchdog/sp5100_tco.c linux-libre-3.8.13-gnu1/drivers/watchdog/sp5100_tco.c
--- linux-libre-3.8-gnu1/drivers/watchdog/sp5100_tco.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/watchdog/sp5100_tco.c	2013-05-11 16:57:46.000000000 -0400
@@ -40,13 +40,12 @@
 #include "sp5100_tco.h"
 
 /* Module and version information */
-#define TCO_VERSION "0.03"
+#define TCO_VERSION "0.05"
 #define TCO_MODULE_NAME "SP5100 TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
 
 /* internal variables */
 static u32 tcobase_phys;
-static u32 resbase_phys;
 static u32 tco_wdt_fired;
 static void __iomem *tcobase;
 static unsigned int pm_iobase;
@@ -54,10 +53,6 @@ static DEFINE_SPINLOCK(tco_lock);	/* Gua
 static unsigned long timer_alive;
 static char tco_expect_close;
 static struct pci_dev *sp5100_tco_pci;
-static struct resource wdt_res = {
-	.name = "Watchdog Timer",
-	.flags = IORESOURCE_MEM,
-};
 
 /* the watchdog platform device */
 static struct platform_device *sp5100_tco_platform_device;
@@ -75,12 +70,6 @@ module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started."
 		" (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static unsigned int force_addr;
-module_param(force_addr, uint, 0);
-MODULE_PARM_DESC(force_addr, "Force the use of specified MMIO address."
-		" ONLY USE THIS PARAMETER IF YOU REALLY KNOW"
-		" WHAT YOU ARE DOING (default=none)");
-
 /*
  * Some TCO specific functions
  */
@@ -176,39 +165,6 @@ static void tco_timer_enable(void)
 	}
 }
 
-static void tco_timer_disable(void)
-{
-	int val;
-
-	if (sp5100_tco_pci->revision >= 0x40) {
-		/* For SB800 or later */
-		/* Enable watchdog decode bit and Disable watchdog timer */
-		outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG);
-		val = inb(SB800_IO_PM_DATA_REG);
-		val |= SB800_PCI_WATCHDOG_DECODE_EN;
-		val |= SB800_PM_WATCHDOG_DISABLE;
-		outb(val, SB800_IO_PM_DATA_REG);
-	} else {
-		/* For SP5100 or SB7x0 */
-		/* Enable watchdog decode bit */
-		pci_read_config_dword(sp5100_tco_pci,
-				      SP5100_PCI_WATCHDOG_MISC_REG,
-				      &val);
-
-		val |= SP5100_PCI_WATCHDOG_DECODE_EN;
-
-		pci_write_config_dword(sp5100_tco_pci,
-				       SP5100_PCI_WATCHDOG_MISC_REG,
-				       val);
-
-		/* Disable Watchdog timer */
-		outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
-		val = inb(SP5100_IO_PM_DATA_REG);
-		val |= SP5100_PM_WATCHDOG_DISABLE;
-		outb(val, SP5100_IO_PM_DATA_REG);
-	}
-}
-
 /*
  *	/dev/watchdog handling
  */
@@ -459,74 +415,8 @@ static unsigned char sp5100_tco_setupdev
 	} else
 		pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val);
 
-	/*
-	 * Lastly re-programming the watchdog timer MMIO address,
-	 * This method is a last resort...
-	 *
-	 * Before re-programming, to ensure that the watchdog timer
-	 * is disabled, disable the watchdog timer.
-	 */
-	tco_timer_disable();
-
-	if (force_addr) {
-		/*
-		 * Force the use of watchdog timer MMIO address, and aligned to
-		 * 8byte boundary.
-		 */
-		force_addr &= ~0x7;
-		val = force_addr;
-
-		pr_info("Force the use of 0x%04x as MMIO address\n", val);
-	} else {
-		/*
-		 * Get empty slot into the resource tree for watchdog timer.
-		 */
-		if (allocate_resource(&iomem_resource,
-				      &wdt_res,
-				      SP5100_WDT_MEM_MAP_SIZE,
-				      0xf0000000,
-				      0xfffffff8,
-				      0x8,
-				      NULL,
-				      NULL)) {
-			pr_err("MMIO allocation failed\n");
-			goto unreg_region;
-		}
-
-		val = resbase_phys = wdt_res.start;
-		pr_debug("Got 0x%04x from resource tree\n", val);
-	}
-
-	/* Restore to the low three bits, if chipset is SB8x0(or later) */
-	if (sp5100_tco_pci->revision >= 0x40) {
-		u8 reserved_bit;
-		reserved_bit = inb(base_addr) & 0x7;
-		val |= (u32)reserved_bit;
-	}
-
-	/* Re-programming the watchdog timer base address */
-	outb(base_addr+0, index_reg);
-	/* Low three bits of BASE are reserved */
-	outb((val >>  0) & 0xf8, data_reg);
-	outb(base_addr+1, index_reg);
-	outb((val >>  8) & 0xff, data_reg);
-	outb(base_addr+2, index_reg);
-	outb((val >> 16) & 0xff, data_reg);
-	outb(base_addr+3, index_reg);
-	outb((val >> 24) & 0xff, data_reg);
-
-	/*
-	 * Clear unnecessary the low three bits,
-	 * if chipset is SB8x0(or later)
-	 */
-	if (sp5100_tco_pci->revision >= 0x40)
-		val &= ~0x7;
-
-	if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
-								   dev_name)) {
-		pr_err("MMIO address 0x%04x already in use\n", val);
-		goto unreg_resource;
-	}
+	pr_notice("failed to find MMIO address, giving up.\n");
+	goto  unreg_region;
 
 setup_wdt:
 	tcobase_phys = val;
@@ -566,9 +456,6 @@ setup_wdt:
 
 unreg_mem_region:
 	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-unreg_resource:
-	if (resbase_phys)
-		release_resource(&wdt_res);
 unreg_region:
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 exit:
@@ -578,7 +465,6 @@ exit:
 static int sp5100_tco_init(struct platform_device *dev)
 {
 	int ret;
-	char addr_str[16];
 
 	/*
 	 * Check whether or not the hardware watchdog is there. If found, then
@@ -610,23 +496,14 @@ static int sp5100_tco_init(struct platfo
 	clear_bit(0, &timer_alive);
 
 	/* Show module parameters */
-	if (force_addr == tcobase_phys)
-		/* The force_addr is vaild */
-		sprintf(addr_str, "0x%04x", force_addr);
-	else
-		strcpy(addr_str, "none");
-
-	pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d, "
-		"force_addr=%s)\n",
-		tcobase, heartbeat, nowayout, addr_str);
+	pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+		tcobase, heartbeat, nowayout);
 
 	return 0;
 
 exit:
 	iounmap(tcobase);
 	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-	if (resbase_phys)
-		release_resource(&wdt_res);
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 	return ret;
 }
@@ -641,8 +518,6 @@ static void sp5100_tco_cleanup(void)
 	misc_deregister(&sp5100_tco_miscdev);
 	iounmap(tcobase);
 	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-	if (resbase_phys)
-		release_resource(&wdt_res);
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 }
 
diff -druNp linux-libre-3.8-gnu1/drivers/watchdog/sp5100_tco.h linux-libre-3.8.13-gnu1/drivers/watchdog/sp5100_tco.h
--- linux-libre-3.8-gnu1/drivers/watchdog/sp5100_tco.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/watchdog/sp5100_tco.h	2013-05-11 16:57:46.000000000 -0400
@@ -57,7 +57,7 @@
 #define SB800_PM_WATCHDOG_DISABLE	(1 << 2)
 #define SB800_PM_WATCHDOG_SECOND_RES	(3 << 0)
 #define SB800_ACPI_MMIO_DECODE_EN	(1 << 0)
-#define SB800_ACPI_MMIO_SEL		(1 << 2)
+#define SB800_ACPI_MMIO_SEL		(1 << 1)
 
 
 #define SB800_PM_WDT_MMIO_OFFSET	0xB00
diff -druNp linux-libre-3.8-gnu1/drivers/xen/events.c linux-libre-3.8.13-gnu1/drivers/xen/events.c
--- linux-libre-3.8-gnu1/drivers/xen/events.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/xen/events.c	2013-05-11 16:57:46.000000000 -0400
@@ -388,11 +388,23 @@ static void unmask_evtchn(int port)
 
 	if (unlikely((cpu != cpu_from_evtchn(port))))
 		do_hypercall = 1;
-	else
+	else {
+		/*
+		 * Need to clear the mask before checking pending to
+		 * avoid a race with an event becoming pending.
+		 *
+		 * EVTCHNOP_unmask will only trigger an upcall if the
+		 * mask bit was set, so if a hypercall is needed
+		 * remask the event.
+		 */
+		sync_clear_bit(port, &s->evtchn_mask[0]);
 		evtchn_pending = sync_test_bit(port, &s->evtchn_pending[0]);
 
-	if (unlikely(evtchn_pending && xen_hvm_domain()))
-		do_hypercall = 1;
+		if (unlikely(evtchn_pending && xen_hvm_domain())) {
+			sync_set_bit(port, &s->evtchn_mask[0]);
+			do_hypercall = 1;
+		}
+	}
 
 	/* Slow path (hypercall) if this is a non-local port or if this is
 	 * an hvm domain and an event is pending (hvm domains don't have
@@ -403,8 +415,6 @@ static void unmask_evtchn(int port)
 	} else {
 		struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
 
-		sync_clear_bit(port, &s->evtchn_mask[0]);
-
 		/*
 		 * The following is basically the equivalent of
 		 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
diff -druNp linux-libre-3.8-gnu1/drivers/xen/evtchn.c linux-libre-3.8.13-gnu1/drivers/xen/evtchn.c
--- linux-libre-3.8-gnu1/drivers/xen/evtchn.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/xen/evtchn.c	2013-05-11 16:57:46.000000000 -0400
@@ -269,6 +269,14 @@ static int evtchn_bind_to_user(struct pe
 				       u->name, (void *)(unsigned long)port);
 	if (rc >= 0)
 		rc = evtchn_make_refcounted(port);
+	else {
+		/* bind failed, should close the port now */
+		struct evtchn_close close;
+		close.port = port;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+			BUG();
+		set_port_user(port, NULL);
+	}
 
 	return rc;
 }
@@ -277,6 +285,8 @@ static void evtchn_unbind_from_user(stru
 {
 	int irq = irq_from_evtchn(port);
 
+	BUG_ON(irq < 0);
+
 	unbind_from_irqhandler(irq, (void *)(unsigned long)port);
 
 	set_port_user(port, NULL);
diff -druNp linux-libre-3.8-gnu1/drivers/xen/fallback.c linux-libre-3.8.13-gnu1/drivers/xen/fallback.c
--- linux-libre-3.8-gnu1/drivers/xen/fallback.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/xen/fallback.c	2013-05-11 16:57:46.000000000 -0400
@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd,
 }
 EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
 
-int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
+int xen_physdev_op_compat(int cmd, void *arg)
 {
 	struct physdev_op op;
 	int rc;
@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd
 
 	return rc;
 }
+EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
diff -druNp linux-libre-3.8-gnu1/drivers/xen/xenbus/xenbus_client.c linux-libre-3.8.13-gnu1/drivers/xen/xenbus/xenbus_client.c
--- linux-libre-3.8-gnu1/drivers/xen/xenbus/xenbus_client.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/xen/xenbus/xenbus_client.c	2013-05-11 16:57:46.000000000 -0400
@@ -30,6 +30,7 @@
  * IN THE SOFTWARE.
  */
 
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
diff -druNp linux-libre-3.8-gnu1/drivers/xen/xen-pciback/pciback_ops.c linux-libre-3.8.13-gnu1/drivers/xen/xen-pciback/pciback_ops.c
--- linux-libre-3.8-gnu1/drivers/xen/xen-pciback/pciback_ops.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/xen/xen-pciback/pciback_ops.c	2013-05-11 16:57:46.000000000 -0400
@@ -113,7 +113,8 @@ void xen_pcibk_reset_device(struct pci_d
 		if (dev->msi_enabled)
 			pci_disable_msi(dev);
 #endif
-		pci_disable_device(dev);
+		if (pci_is_enabled(dev))
+			pci_disable_device(dev);
 
 		pci_write_config_word(dev, PCI_COMMAND, 0);
 
diff -druNp linux-libre-3.8-gnu1/drivers/xen/xen-pciback/pci_stub.c linux-libre-3.8.13-gnu1/drivers/xen/xen-pciback/pci_stub.c
--- linux-libre-3.8-gnu1/drivers/xen/xen-pciback/pci_stub.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/drivers/xen/xen-pciback/pci_stub.c	2013-05-11 16:57:46.000000000 -0400
@@ -17,6 +17,7 @@
 #include <xen/events.h>
 #include <asm/xen/pci.h>
 #include <asm/xen/hypervisor.h>
+#include <xen/interface/physdev.h>
 #include "pciback.h"
 #include "conf_space.h"
 #include "conf_space_quirks.h"
@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_de
 static void pcistub_device_release(struct kref *kref)
 {
 	struct pcistub_device *psdev;
+	struct pci_dev *dev;
 	struct xen_pcibk_dev_data *dev_data;
 
 	psdev = container_of(kref, struct pcistub_device, kref);
-	dev_data = pci_get_drvdata(psdev->dev);
+	dev = psdev->dev;
+	dev_data = pci_get_drvdata(dev);
 
-	dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
+	dev_dbg(&dev->dev, "pcistub_device_release\n");
 
-	xen_unregister_device_domain_owner(psdev->dev);
+	xen_unregister_device_domain_owner(dev);
 
 	/* Call the reset function which does not take lock as this
 	 * is called from "unbind" which takes a device_lock mutex.
 	 */
-	__pci_reset_function_locked(psdev->dev);
-	if (pci_load_and_free_saved_state(psdev->dev,
-					  &dev_data->pci_saved_state)) {
-		dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n");
-	} else
-		pci_restore_state(psdev->dev);
+	__pci_reset_function_locked(dev);
+	if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
+		dev_dbg(&dev->dev, "Could not reload PCI state\n");
+	else
+		pci_restore_state(dev);
+
+	if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
+		struct physdev_pci_device ppdev = {
+			.seg = pci_domain_nr(dev->bus),
+			.bus = dev->bus->number,
+			.devfn = dev->devfn
+		};
+		int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix,
+						&ppdev);
+
+		if (err)
+			dev_warn(&dev->dev, "MSI-X release failed (%d)\n",
+				 err);
+	}
 
 	/* Disable the device */
-	xen_pcibk_reset_device(psdev->dev);
+	xen_pcibk_reset_device(dev);
 
 	kfree(dev_data);
-	pci_set_drvdata(psdev->dev, NULL);
+	pci_set_drvdata(dev, NULL);
 
 	/* Clean-up the device */
-	xen_pcibk_config_free_dyn_fields(psdev->dev);
-	xen_pcibk_config_free_dev(psdev->dev);
+	xen_pcibk_config_free_dyn_fields(dev);
+	xen_pcibk_config_free_dev(dev);
 
-	psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
-	pci_dev_put(psdev->dev);
+	dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
+	pci_dev_put(dev);
 
 	kfree(psdev);
 }
@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pc
 	if (err)
 		goto config_release;
 
+	if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
+		struct physdev_pci_device ppdev = {
+			.seg = pci_domain_nr(dev->bus),
+			.bus = dev->bus->number,
+			.devfn = dev->devfn
+		};
+
+		err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev);
+		if (err)
+			dev_err(&dev->dev, "MSI-X preparation failed (%d)\n",
+				err);
+	}
+
 	/* We need the device active to save the state. */
 	dev_dbg(&dev->dev, "save state of device\n");
 	pci_save_state(dev);
diff -druNp linux-libre-3.8-gnu1/fs/aio.c linux-libre-3.8.13-gnu1/fs/aio.c
--- linux-libre-3.8-gnu1/fs/aio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/aio.c	2013-05-11 16:57:46.000000000 -0400
@@ -1027,9 +1027,9 @@ static int aio_read_evt(struct kioctx *i
 	spin_unlock(&info->ring_lock);
 
 out:
-	kunmap_atomic(ring);
 	dprintk("leaving aio_read_evt: %d  h%lu t%lu\n", ret,
 		 (unsigned long)ring->head, (unsigned long)ring->tail);
+	kunmap_atomic(ring);
 	return ret;
 }
 
diff -druNp linux-libre-3.8-gnu1/fs/autofs4/expire.c linux-libre-3.8.13-gnu1/fs/autofs4/expire.c
--- linux-libre-3.8-gnu1/fs/autofs4/expire.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/autofs4/expire.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,15 +61,6 @@ static int autofs4_mount_busy(struct vfs
 		/* This is an autofs submount, we can't expire it */
 		if (autofs_type_indirect(sbi->type))
 			goto done;
-
-		/*
-		 * Otherwise it's an offset mount and we need to check
-		 * if we can umount its mount, if there is one.
-		 */
-		if (!d_mountpoint(path.dentry)) {
-			status = 0;
-			goto done;
-		}
 	}
 
 	/* Update the expiry counter if fs is busy */
diff -druNp linux-libre-3.8-gnu1/fs/binfmt_elf.c linux-libre-3.8.13-gnu1/fs/binfmt_elf.c
--- linux-libre-3.8-gnu1/fs/binfmt_elf.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/binfmt_elf.c	2013-05-11 16:57:46.000000000 -0400
@@ -1132,6 +1132,7 @@ static unsigned long vma_dump_size(struc
 			goto whole;
 		if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE))
 			goto whole;
+		return 0;
 	}
 
 	/* Do not dump I/O mapped devices or special mappings */
diff -druNp linux-libre-3.8-gnu1/fs/block_dev.c linux-libre-3.8.13-gnu1/fs/block_dev.c
--- linux-libre-3.8-gnu1/fs/block_dev.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/block_dev.c	2013-05-11 16:57:46.000000000 -0400
@@ -551,6 +551,7 @@ struct block_device *bdgrab(struct block
 	ihold(bdev->bd_inode);
 	return bdev;
 }
+EXPORT_SYMBOL(bdgrab);
 
 long nr_blockdev_pages(void)
 {
@@ -994,6 +995,7 @@ int revalidate_disk(struct gendisk *disk
 
 	mutex_lock(&bdev->bd_mutex);
 	check_disk_size_change(disk, bdev);
+	bdev->bd_invalidated = 0;
 	mutex_unlock(&bdev->bd_mutex);
 	bdput(bdev);
 	return ret;
@@ -1032,7 +1034,9 @@ void bd_set_size(struct block_device *bd
 {
 	unsigned bsize = bdev_logical_block_size(bdev);
 
-	bdev->bd_inode->i_size = size;
+	mutex_lock(&bdev->bd_inode->i_mutex);
+	i_size_write(bdev->bd_inode, size);
+	mutex_unlock(&bdev->bd_inode->i_mutex);
 	while (bsize < PAGE_CACHE_SIZE) {
 		if (size & bsize)
 			break;
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/ctree.c linux-libre-3.8.13-gnu1/fs/btrfs/ctree.c
--- linux-libre-3.8-gnu1/fs/btrfs/ctree.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/ctree.c	2013-05-11 16:57:46.000000000 -0400
@@ -651,6 +651,8 @@ tree_mod_log_insert_root(struct btrfs_fs
 	if (tree_mod_dont_log(fs_info, NULL))
 		return 0;
 
+	__tree_mod_log_free_eb(fs_info, old_root);
+
 	ret = tree_mod_alloc(fs_info, flags, &tm);
 	if (ret < 0)
 		goto out;
@@ -736,7 +738,7 @@ tree_mod_log_search(struct btrfs_fs_info
 static noinline void
 tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst,
 		     struct extent_buffer *src, unsigned long dst_offset,
-		     unsigned long src_offset, int nr_items)
+		     unsigned long src_offset, int nr_items, int log_removal)
 {
 	int ret;
 	int i;
@@ -750,10 +752,12 @@ tree_mod_log_eb_copy(struct btrfs_fs_inf
 	}
 
 	for (i = 0; i < nr_items; i++) {
-		ret = tree_mod_log_insert_key_locked(fs_info, src,
-						     i + src_offset,
-						     MOD_LOG_KEY_REMOVE);
-		BUG_ON(ret < 0);
+		if (log_removal) {
+			ret = tree_mod_log_insert_key_locked(fs_info, src,
+							i + src_offset,
+							MOD_LOG_KEY_REMOVE);
+			BUG_ON(ret < 0);
+		}
 		ret = tree_mod_log_insert_key_locked(fs_info, dst,
 						     i + dst_offset,
 						     MOD_LOG_KEY_ADD);
@@ -927,7 +931,6 @@ static noinline int update_ref_for_cow(s
 			ret = btrfs_dec_ref(trans, root, buf, 1, 1);
 			BUG_ON(ret); /* -ENOMEM */
 		}
-		tree_mod_log_free_eb(root->fs_info, buf);
 		clean_tree_block(trans, root, buf);
 		*last_ref = 1;
 	}
@@ -1046,6 +1049,7 @@ static noinline int __btrfs_cow_block(st
 		btrfs_set_node_ptr_generation(parent, parent_slot,
 					      trans->transid);
 		btrfs_mark_buffer_dirty(parent);
+		tree_mod_log_free_eb(root->fs_info, buf);
 		btrfs_free_tree_block(trans, root, buf, parent_start,
 				      last_ref);
 	}
@@ -1755,7 +1759,6 @@ static noinline int balance_level(struct
 			goto enospc;
 		}
 
-		tree_mod_log_free_eb(root->fs_info, root->node);
 		tree_mod_log_set_root_pointer(root, child);
 		rcu_assign_pointer(root->node, child);
 
@@ -3000,7 +3003,7 @@ static int push_node_left(struct btrfs_t
 		push_items = min(src_nritems - 8, push_items);
 
 	tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0,
-			     push_items);
+			     push_items, 1);
 	copy_extent_buffer(dst, src,
 			   btrfs_node_key_ptr_offset(dst_nritems),
 			   btrfs_node_key_ptr_offset(0),
@@ -3071,7 +3074,7 @@ static int balance_node_right(struct btr
 				      sizeof(struct btrfs_key_ptr));
 
 	tree_mod_log_eb_copy(root->fs_info, dst, src, 0,
-			     src_nritems - push_items, push_items);
+			     src_nritems - push_items, push_items, 1);
 	copy_extent_buffer(dst, src,
 			   btrfs_node_key_ptr_offset(0),
 			   btrfs_node_key_ptr_offset(src_nritems - push_items),
@@ -3223,12 +3226,18 @@ static noinline int split_node(struct bt
 	int mid;
 	int ret;
 	u32 c_nritems;
+	int tree_mod_log_removal = 1;
 
 	c = path->nodes[level];
 	WARN_ON(btrfs_header_generation(c) != trans->transid);
 	if (c == root->node) {
 		/* trying to split the root, lets make a new one */
 		ret = insert_new_root(trans, root, path, level + 1);
+		/*
+		 * removal of root nodes has been logged by
+		 * tree_mod_log_set_root_pointer due to locking
+		 */
+		tree_mod_log_removal = 0;
 		if (ret)
 			return ret;
 	} else {
@@ -3266,7 +3275,8 @@ static noinline int split_node(struct bt
 			    (unsigned long)btrfs_header_chunk_tree_uuid(split),
 			    BTRFS_UUID_SIZE);
 
-	tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid);
+	tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid,
+			     tree_mod_log_removal);
 	copy_extent_buffer(split, c,
 			   btrfs_node_key_ptr_offset(0),
 			   btrfs_node_key_ptr_offset(mid),
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/delayed-ref.c linux-libre-3.8.13-gnu1/fs/btrfs/delayed-ref.c
--- linux-libre-3.8-gnu1/fs/btrfs/delayed-ref.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/delayed-ref.c	2013-05-11 16:57:46.000000000 -0400
@@ -36,16 +36,19 @@
  * compare two delayed tree backrefs with same bytenr and type
  */
 static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2,
-			  struct btrfs_delayed_tree_ref *ref1)
+			  struct btrfs_delayed_tree_ref *ref1, int type)
 {
-	if (ref1->root < ref2->root)
-		return -1;
-	if (ref1->root > ref2->root)
-		return 1;
-	if (ref1->parent < ref2->parent)
-		return -1;
-	if (ref1->parent > ref2->parent)
-		return 1;
+	if (type == BTRFS_TREE_BLOCK_REF_KEY) {
+		if (ref1->root < ref2->root)
+			return -1;
+		if (ref1->root > ref2->root)
+			return 1;
+	} else {
+		if (ref1->parent < ref2->parent)
+			return -1;
+		if (ref1->parent > ref2->parent)
+			return 1;
+	}
 	return 0;
 }
 
@@ -109,7 +112,8 @@ static int comp_entry(struct btrfs_delay
 	if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
 	    ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) {
 		return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2),
-				      btrfs_delayed_node_to_tree_ref(ref1));
+				      btrfs_delayed_node_to_tree_ref(ref1),
+				      ref1->type);
 	} else if (ref1->type == BTRFS_EXTENT_DATA_REF_KEY ||
 		   ref1->type == BTRFS_SHARED_DATA_REF_KEY) {
 		return comp_data_refs(btrfs_delayed_node_to_data_ref(ref2),
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/extent_io.c linux-libre-3.8.13-gnu1/fs/btrfs/extent_io.c
--- linux-libre-3.8-gnu1/fs/btrfs/extent_io.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/extent_io.c	2013-05-11 16:57:46.000000000 -0400
@@ -1258,6 +1258,39 @@ int unlock_extent(struct extent_io_tree
 				GFP_NOFS);
 }
 
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+	unsigned long index = start >> PAGE_CACHE_SHIFT;
+	unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+	struct page *page;
+
+	while (index <= end_index) {
+		page = find_get_page(inode->i_mapping, index);
+		BUG_ON(!page); /* Pages should be in the extent_io_tree */
+		clear_page_dirty_for_io(page);
+		page_cache_release(page);
+		index++;
+	}
+	return 0;
+}
+
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+	unsigned long index = start >> PAGE_CACHE_SHIFT;
+	unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+	struct page *page;
+
+	while (index <= end_index) {
+		page = find_get_page(inode->i_mapping, index);
+		BUG_ON(!page); /* Pages should be in the extent_io_tree */
+		account_page_redirty(page);
+		__set_page_dirty_nobuffers(page);
+		page_cache_release(page);
+		index++;
+	}
+	return 0;
+}
+
 /*
  * helper function to set both pages and extents in the tree writeback
  */
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/extent_io.h linux-libre-3.8.13-gnu1/fs/btrfs/extent_io.h
--- linux-libre-3.8-gnu1/fs/btrfs/extent_io.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/extent_io.h	2013-05-11 16:57:46.000000000 -0400
@@ -329,6 +329,8 @@ int map_private_extent_buffer(struct ext
 		      unsigned long *map_len);
 int extent_range_uptodate(struct extent_io_tree *tree,
 			  u64 start, u64 end);
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
 int extent_clear_unlock_delalloc(struct inode *inode,
 				struct extent_io_tree *tree,
 				u64 start, u64 end, struct page *locked_page,
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/extent-tree.c linux-libre-3.8.13-gnu1/fs/btrfs/extent-tree.c
--- linux-libre-3.8-gnu1/fs/btrfs/extent-tree.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/extent-tree.c	2013-05-11 16:57:46.000000000 -0400
@@ -4308,7 +4308,7 @@ static void update_global_block_rsv(stru
 	spin_lock(&sinfo->lock);
 	spin_lock(&block_rsv->lock);
 
-	block_rsv->size = num_bytes;
+	block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024);
 
 	num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
 		    sinfo->bytes_reserved + sinfo->bytes_readonly +
@@ -4601,14 +4601,49 @@ int btrfs_delalloc_reserve_metadata(stru
 		 * If the inodes csum_bytes is the same as the original
 		 * csum_bytes then we know we haven't raced with any free()ers
 		 * so we can just reduce our inodes csum bytes and carry on.
-		 * Otherwise we have to do the normal free thing to account for
-		 * the case that the free side didn't free up its reserve
-		 * because of this outstanding reservation.
 		 */
-		if (BTRFS_I(inode)->csum_bytes == csum_bytes)
+		if (BTRFS_I(inode)->csum_bytes == csum_bytes) {
 			calc_csum_metadata_size(inode, num_bytes, 0);
-		else
-			to_free = calc_csum_metadata_size(inode, num_bytes, 0);
+		} else {
+			u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes;
+			u64 bytes;
+
+			/*
+			 * This is tricky, but first we need to figure out how much we
+			 * free'd from any free-ers that occured during this
+			 * reservation, so we reset ->csum_bytes to the csum_bytes
+			 * before we dropped our lock, and then call the free for the
+			 * number of bytes that were freed while we were trying our
+			 * reservation.
+			 */
+			bytes = csum_bytes - BTRFS_I(inode)->csum_bytes;
+			BTRFS_I(inode)->csum_bytes = csum_bytes;
+			to_free = calc_csum_metadata_size(inode, bytes, 0);
+
+
+			/*
+			 * Now we need to see how much we would have freed had we not
+			 * been making this reservation and our ->csum_bytes were not
+			 * artificially inflated.
+			 */
+			BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes;
+			bytes = csum_bytes - orig_csum_bytes;
+			bytes = calc_csum_metadata_size(inode, bytes, 0);
+
+			/*
+			 * Now reset ->csum_bytes to what it should be.  If bytes is
+			 * more than to_free then we would have free'd more space had we
+			 * not had an artificially high ->csum_bytes, so we need to free
+			 * the remainder.  If bytes is the same or less then we don't
+			 * need to do anything, the other free-ers did the correct
+			 * thing.
+			 */
+			BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes;
+			if (bytes > to_free)
+				to_free = bytes - to_free;
+			else
+				to_free = 0;
+		}
 		spin_unlock(&BTRFS_I(inode)->lock);
 		if (dropped)
 			to_free += btrfs_calc_trans_metadata_size(root, dropped);
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/inode.c linux-libre-3.8.13-gnu1/fs/btrfs/inode.c
--- linux-libre-3.8-gnu1/fs/btrfs/inode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/inode.c	2013-05-11 16:57:46.000000000 -0400
@@ -265,6 +265,7 @@ static noinline int cow_file_range_inlin
 		return 1;
 	}
 
+	set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags);
 	btrfs_delalloc_release_metadata(inode, end + 1 - start);
 	btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0);
 	return 0;
@@ -351,6 +352,7 @@ static noinline int compress_file_range(
 	int i;
 	int will_compress;
 	int compress_type = root->fs_info->compress_type;
+	int redirty = 0;
 
 	/* if this is a small write inside eof, kick off a defrag */
 	if ((end - start + 1) < 16 * 1024 &&
@@ -413,6 +415,17 @@ again:
 		if (BTRFS_I(inode)->force_compress)
 			compress_type = BTRFS_I(inode)->force_compress;
 
+		/*
+		 * we need to call clear_page_dirty_for_io on each
+		 * page in the range.  Otherwise applications with the file
+		 * mmap'd can wander in and change the page contents while
+		 * we are compressing them.
+		 *
+		 * If the compression fails for any reason, we set the pages
+		 * dirty again later on.
+		 */
+		extent_range_clear_dirty_for_io(inode, start, end);
+		redirty = 1;
 		ret = btrfs_compress_pages(compress_type,
 					   inode->i_mapping, start,
 					   total_compressed, pages,
@@ -554,6 +567,8 @@ cleanup_and_bail_uncompressed:
 			__set_page_dirty_nobuffers(locked_page);
 			/* unlocked later on in the async handlers */
 		}
+		if (redirty)
+			extent_range_redirty_for_io(inode, start, end);
 		add_async_extent(async_cow, start, end - start + 1,
 				 0, NULL, 0, BTRFS_COMPRESS_NONE);
 		*num_added += 1;
@@ -2469,6 +2484,7 @@ int btrfs_orphan_cleanup(struct btrfs_ro
 		 */
 		set_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
 			&BTRFS_I(inode)->runtime_flags);
+		atomic_inc(&root->orphan_inodes);
 
 		/* if we have links, this was a truncate, lets do that */
 		if (inode->i_nlink) {
@@ -2491,6 +2507,8 @@ int btrfs_orphan_cleanup(struct btrfs_ro
 				goto out;
 
 			ret = btrfs_truncate(inode);
+			if (ret)
+				btrfs_orphan_del(NULL, inode);
 		} else {
 			nr_unlink++;
 		}
@@ -5776,7 +5794,9 @@ out:
  * block must be cow'd
  */
 static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
-				      struct inode *inode, u64 offset, u64 len)
+				      struct inode *inode, u64 offset, u64 *len,
+				      u64 *orig_start, u64 *orig_block_len,
+				      u64 *ram_bytes)
 {
 	struct btrfs_path *path;
 	int ret;
@@ -5833,8 +5853,12 @@ static noinline int can_nocow_odirect(st
 	disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
 	backref_offset = btrfs_file_extent_offset(leaf, fi);
 
+	*orig_start = key.offset - backref_offset;
+	*orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
+	*ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
+
 	extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
-	if (extent_end < offset + len) {
+	if (extent_end < offset + *len) {
 		/* extent doesn't include our full range, must cow */
 		goto out;
 	}
@@ -5858,13 +5882,14 @@ static noinline int can_nocow_odirect(st
 	 */
 	disk_bytenr += backref_offset;
 	disk_bytenr += offset - key.offset;
-	num_bytes = min(offset + len, extent_end) - offset;
+	num_bytes = min(offset + *len, extent_end) - offset;
 	if (csum_exist_in_range(root, disk_bytenr, num_bytes))
 				goto out;
 	/*
 	 * all of the above have passed, it is safe to overwrite this extent
 	 * without cow
 	 */
+	*len = num_bytes;
 	ret = 1;
 out:
 	btrfs_free_path(path);
@@ -6074,7 +6099,7 @@ static int btrfs_get_blocks_direct(struc
 	     em->block_start != EXTENT_MAP_HOLE)) {
 		int type;
 		int ret;
-		u64 block_start;
+		u64 block_start, orig_start, orig_block_len, ram_bytes;
 
 		if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
 			type = BTRFS_ORDERED_PREALLOC;
@@ -6092,10 +6117,8 @@ static int btrfs_get_blocks_direct(struc
 		if (IS_ERR(trans))
 			goto must_cow;
 
-		if (can_nocow_odirect(trans, inode, start, len) == 1) {
-			u64 orig_start = em->orig_start;
-			u64 orig_block_len = em->orig_block_len;
-
+		if (can_nocow_odirect(trans, inode, start, &len, &orig_start,
+				      &orig_block_len, &ram_bytes) == 1) {
 			if (type == BTRFS_ORDERED_PREALLOC) {
 				free_extent_map(em);
 				em = create_pinned_em(inode, start, len,
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/scrub.c linux-libre-3.8.13-gnu1/fs/btrfs/scrub.c
--- linux-libre-3.8-gnu1/fs/btrfs/scrub.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/scrub.c	2013-05-11 16:57:46.000000000 -0400
@@ -541,7 +541,6 @@ static void scrub_print_warning(const ch
 	eb = path->nodes[0];
 	ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
 	item_size = btrfs_item_size_nr(eb, path->slots[0]);
-	btrfs_release_path(path);
 
 	if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
 		do {
@@ -557,7 +556,9 @@ static void scrub_print_warning(const ch
 				ret < 0 ? -1 : ref_level,
 				ret < 0 ? -1 : ref_root);
 		} while (ret != 1);
+		btrfs_release_path(path);
 	} else {
+		btrfs_release_path(path);
 		swarn.path = path;
 		swarn.dev = dev;
 		iterate_extent_inodes(fs_info, found_key.objectid,
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/tree-log.c linux-libre-3.8.13-gnu1/fs/btrfs/tree-log.c
--- linux-libre-3.8-gnu1/fs/btrfs/tree-log.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/tree-log.c	2013-05-11 16:57:46.000000000 -0400
@@ -318,6 +318,7 @@ static noinline int overwrite_item(struc
 	unsigned long src_ptr;
 	unsigned long dst_ptr;
 	int overwrite_root = 0;
+	bool inode_item = key->type == BTRFS_INODE_ITEM_KEY;
 
 	if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
 		overwrite_root = 1;
@@ -327,6 +328,9 @@ static noinline int overwrite_item(struc
 
 	/* look for the key in the destination tree */
 	ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+	if (ret < 0)
+		return ret;
+
 	if (ret == 0) {
 		char *src_copy;
 		char *dst_copy;
@@ -368,6 +372,30 @@ static noinline int overwrite_item(struc
 			return 0;
 		}
 
+		/*
+		 * We need to load the old nbytes into the inode so when we
+		 * replay the extents we've logged we get the right nbytes.
+		 */
+		if (inode_item) {
+			struct btrfs_inode_item *item;
+			u64 nbytes;
+
+			item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+					      struct btrfs_inode_item);
+			nbytes = btrfs_inode_nbytes(path->nodes[0], item);
+			item = btrfs_item_ptr(eb, slot,
+					      struct btrfs_inode_item);
+			btrfs_set_inode_nbytes(eb, item, nbytes);
+		}
+	} else if (inode_item) {
+		struct btrfs_inode_item *item;
+
+		/*
+		 * New inode, set nbytes to 0 so that the nbytes comes out
+		 * properly when we replay the extents.
+		 */
+		item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
+		btrfs_set_inode_nbytes(eb, item, 0);
 	}
 insert:
 	btrfs_release_path(path);
@@ -488,7 +516,7 @@ static noinline int replay_one_extent(st
 	u64 mask = root->sectorsize - 1;
 	u64 extent_end;
 	u64 start = key->offset;
-	u64 saved_nbytes;
+	u64 nbytes = 0;
 	struct btrfs_file_extent_item *item;
 	struct inode *inode = NULL;
 	unsigned long size;
@@ -498,10 +526,19 @@ static noinline int replay_one_extent(st
 	found_type = btrfs_file_extent_type(eb, item);
 
 	if (found_type == BTRFS_FILE_EXTENT_REG ||
-	    found_type == BTRFS_FILE_EXTENT_PREALLOC)
-		extent_end = start + btrfs_file_extent_num_bytes(eb, item);
-	else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
+	    found_type == BTRFS_FILE_EXTENT_PREALLOC) {
+		nbytes = btrfs_file_extent_num_bytes(eb, item);
+		extent_end = start + nbytes;
+
+		/*
+		 * We don't add to the inodes nbytes if we are prealloc or a
+		 * hole.
+		 */
+		if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
+			nbytes = 0;
+	} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
 		size = btrfs_file_extent_inline_len(eb, item);
+		nbytes = btrfs_file_extent_ram_bytes(eb, item);
 		extent_end = (start + size + mask) & ~mask;
 	} else {
 		ret = 0;
@@ -550,7 +587,6 @@ static noinline int replay_one_extent(st
 	}
 	btrfs_release_path(path);
 
-	saved_nbytes = inode_get_bytes(inode);
 	/* drop any overlapping extents */
 	ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1);
 	BUG_ON(ret);
@@ -637,7 +673,7 @@ static noinline int replay_one_extent(st
 		BUG_ON(ret);
 	}
 
-	inode_set_bytes(inode, saved_nbytes);
+	inode_add_bytes(inode, nbytes);
 	ret = btrfs_update_inode(trans, root, inode);
 out:
 	if (inode)
@@ -1384,7 +1420,10 @@ static noinline int link_to_fixup_dir(st
 
 	btrfs_release_path(path);
 	if (ret == 0) {
-		btrfs_inc_nlink(inode);
+		if (!inode->i_nlink)
+			set_nlink(inode, 1);
+		else
+			btrfs_inc_nlink(inode);
 		ret = btrfs_update_inode(trans, root, inode);
 	} else if (ret == -EEXIST) {
 		ret = 0;
@@ -3281,6 +3320,7 @@ static int log_one_extent(struct btrfs_t
 	int ret;
 	bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
+insert:
 	INIT_LIST_HEAD(&ordered_sums);
 	btrfs_init_map_token(&token);
 	key.objectid = btrfs_ino(inode);
@@ -3296,6 +3336,23 @@ static int log_one_extent(struct btrfs_t
 	leaf = path->nodes[0];
 	fi = btrfs_item_ptr(leaf, path->slots[0],
 			    struct btrfs_file_extent_item);
+
+	/*
+	 * If we are overwriting an inline extent with a real one then we need
+	 * to just delete the inline extent as it may not be large enough to
+	 * have the entire file_extent_item.
+	 */
+	if (ret && btrfs_token_file_extent_type(leaf, fi, &token) ==
+	    BTRFS_FILE_EXTENT_INLINE) {
+		ret = btrfs_del_item(trans, log, path);
+		btrfs_release_path(path);
+		if (ret) {
+			path->really_keep_locks = 0;
+			return ret;
+		}
+		goto insert;
+	}
+
 	btrfs_set_token_file_extent_generation(leaf, fi, em->generation,
 					       &token);
 	if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
diff -druNp linux-libre-3.8-gnu1/fs/btrfs/volumes.c linux-libre-3.8.13-gnu1/fs/btrfs/volumes.c
--- linux-libre-3.8-gnu1/fs/btrfs/volumes.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/btrfs/volumes.c	2013-05-11 16:57:46.000000000 -0400
@@ -647,6 +647,7 @@ static int __btrfs_close_devices(struct
 		new_device->writeable = 0;
 		new_device->in_fs_metadata = 0;
 		new_device->can_discard = 0;
+		spin_lock_init(&new_device->io_lock);
 		list_replace_rcu(&device->dev_list, &new_device->dev_list);
 
 		call_rcu(&device->rcu, free_device);
@@ -680,6 +681,12 @@ int btrfs_close_devices(struct btrfs_fs_
 		__btrfs_close_devices(fs_devices);
 		free_fs_devices(fs_devices);
 	}
+	/*
+	 * Wait for rcu kworkers under __btrfs_close_devices
+	 * to finish all blkdev_puts so device is really
+	 * free when umount is done.
+	 */
+	rcu_barrier();
 	return ret;
 }
 
diff -druNp linux-libre-3.8-gnu1/fs/cifs/asn1.c linux-libre-3.8.13-gnu1/fs/cifs/asn1.c
--- linux-libre-3.8-gnu1/fs/cifs/asn1.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/cifs/asn1.c	2013-05-11 16:57:46.000000000 -0400
@@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *secur
 		}
 	}
 
-	/* mechlistMIC */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		/* Check if we have reached the end of the blob, but with
-		   no mechListMic (e.g. NTLMSSP instead of KRB5) */
-		if (ctx.error == ASN1_ERR_DEC_EMPTY)
-			goto decode_negtoken_exit;
-		cFYI(1, "Error decoding last part negTokenInit exit3");
-		return 0;
-	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
-		/* tag = 3 indicating mechListMIC */
-		cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-		return 0;
-	}
-
-	/* sequence */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding last part negTokenInit exit5");
-		return 0;
-	} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
-		   || (tag != ASN1_SEQ)) {
-		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-	}
-
-	/* sequence of */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding last part negTokenInit exit 7");
-		return 0;
-	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
-		cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-		return 0;
-	}
-
-	/* general string */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding last part negTokenInit exit9");
-		return 0;
-	} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
-		   || (tag != ASN1_GENSTR)) {
-		cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-		return 0;
-	}
-	cFYI(1, "Need to call asn1_octets_decode() function for %s",
-		ctx.pointer);	/* is this UTF-8 or ASCII? */
-decode_negtoken_exit:
+	/*
+	 * We currently ignore anything at the end of the SPNEGO blob after
+	 * the mechTypes have been parsed, since none of that info is
+	 * used at the moment.
+	 */
 	return 1;
 }
diff -druNp linux-libre-3.8-gnu1/fs/cifs/cifsfs.c linux-libre-3.8.13-gnu1/fs/cifs/cifsfs.c
--- linux-libre-3.8-gnu1/fs/cifs/cifsfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/cifs/cifsfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -91,6 +91,30 @@ struct workqueue_struct	*cifsiod_wq;
 __u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
 #endif
 
+/*
+ * Bumps refcount for cifs super block.
+ * Note that it should be only called if a referece to VFS super block is
+ * already held, e.g. in open-type syscalls context. Otherwise it can race with
+ * atomic_dec_and_test in deactivate_locked_super.
+ */
+void
+cifs_sb_active(struct super_block *sb)
+{
+	struct cifs_sb_info *server = CIFS_SB(sb);
+
+	if (atomic_inc_return(&server->active) == 1)
+		atomic_inc(&sb->s_active);
+}
+
+void
+cifs_sb_deactive(struct super_block *sb)
+{
+	struct cifs_sb_info *server = CIFS_SB(sb);
+
+	if (atomic_dec_and_test(&server->active))
+		deactivate_super(sb);
+}
+
 static int
 cifs_read_super(struct super_block *sb)
 {
@@ -558,6 +582,11 @@ cifs_get_root(struct smb_vol *vol, struc
 			dentry = ERR_PTR(-ENOENT);
 			break;
 		}
+		if (!S_ISDIR(dir->i_mode)) {
+			dput(dentry);
+			dentry = ERR_PTR(-ENOTDIR);
+			break;
+		}
 
 		/* skip separators */
 		while (*s == sep)
diff -druNp linux-libre-3.8-gnu1/fs/cifs/cifsfs.h linux-libre-3.8.13-gnu1/fs/cifs/cifsfs.h
--- linux-libre-3.8-gnu1/fs/cifs/cifsfs.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/cifs/cifsfs.h	2013-05-11 16:57:46.000000000 -0400
@@ -41,6 +41,10 @@ extern struct file_system_type cifs_fs_t
 extern const struct address_space_operations cifs_addr_ops;
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
+/* Functions related to super block operations */
+extern void cifs_sb_active(struct super_block *sb);
+extern void cifs_sb_deactive(struct super_block *sb);
+
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
 extern struct inode *cifs_root_iget(struct super_block *);
diff -druNp linux-libre-3.8-gnu1/fs/cifs/connect.c linux-libre-3.8.13-gnu1/fs/cifs/connect.c
--- linux-libre-3.8-gnu1/fs/cifs/connect.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/cifs/connect.c	2013-05-11 16:57:46.000000000 -0400
@@ -1546,14 +1546,24 @@ cifs_parse_mount_options(const char *mou
 			}
 			break;
 		case Opt_blank_pass:
-			vol->password = NULL;
-			break;
-		case Opt_pass:
 			/* passwords have to be handled differently
 			 * to allow the character used for deliminator
 			 * to be passed within them
 			 */
 
+			/*
+			 * Check if this is a case where the  password
+			 * starts with a delimiter
+			 */
+			tmp_end = strchr(data, '=');
+			tmp_end++;
+			if (!(tmp_end < end && tmp_end[1] == delim)) {
+				/* No it is not. Set the password to NULL */
+				vol->password = NULL;
+				break;
+			}
+			/* Yes it is. Drop down to Opt_pass below.*/
+		case Opt_pass:
 			/* Obtain the value string */
 			value = strchr(data, '=');
 			value++;
diff -druNp linux-libre-3.8-gnu1/fs/cifs/file.c linux-libre-3.8.13-gnu1/fs/cifs/file.c
--- linux-libre-3.8-gnu1/fs/cifs/file.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/cifs/file.c	2013-05-11 16:57:46.000000000 -0400
@@ -294,6 +294,8 @@ cifs_new_fileinfo(struct cifs_fid *fid,
 	INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
 	mutex_init(&cfile->fh_mutex);
 
+	cifs_sb_active(inode->i_sb);
+
 	/*
 	 * If the server returned a read oplock and we have mandatory brlocks,
 	 * set oplock level to None.
@@ -343,7 +345,8 @@ void cifsFileInfo_put(struct cifsFileInf
 	struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
 	struct TCP_Server_Info *server = tcon->ses->server;
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
-	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct super_block *sb = inode->i_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	struct cifsLockInfo *li, *tmp;
 	struct cifs_fid fid;
 	struct cifs_pending_open open;
@@ -408,6 +411,7 @@ void cifsFileInfo_put(struct cifsFileInf
 
 	cifs_put_tlink(cifs_file->tlink);
 	dput(cifs_file->dentry);
+	cifs_sb_deactive(sb);
 	kfree(cifs_file);
 }
 
diff -druNp linux-libre-3.8-gnu1/fs/cifs/smb2ops.c linux-libre-3.8.13-gnu1/fs/cifs/smb2ops.c
--- linux-libre-3.8-gnu1/fs/cifs/smb2ops.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/cifs/smb2ops.c	2013-05-11 16:57:46.000000000 -0400
@@ -744,4 +744,5 @@ struct smb_version_values smb30_values =
 	.cap_unix = 0,
 	.cap_nt_find = SMB2_NT_FIND,
 	.cap_large_files = SMB2_LARGE_FILES,
+	.oplock_read = SMB2_OPLOCK_LEVEL_II,
 };
diff -druNp linux-libre-3.8-gnu1/fs/compat.c linux-libre-3.8.13-gnu1/fs/compat.c
--- linux-libre-3.8-gnu1/fs/compat.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/compat.c	2013-05-11 16:57:46.000000000 -0400
@@ -558,6 +558,10 @@ ssize_t compat_rw_copy_check_uvector(int
 	}
 	*ret_pointer = iov;
 
+	ret = -EFAULT;
+	if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+		goto out;
+
 	/*
 	 * Single unix specification:
 	 * We should -EINVAL if an element length is not >= 0 and fitting an
@@ -1080,17 +1084,12 @@ static ssize_t compat_do_readv_writev(in
 	if (!file->f_op)
 		goto out;
 
-	ret = -EFAULT;
-	if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
-		goto out;
-
-	tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+	ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
 					       UIO_FASTIOV, iovstack, &iov);
-	if (tot_len == 0) {
-		ret = 0;
+	if (ret <= 0)
 		goto out;
-	}
 
+	tot_len = ret;
 	ret = rw_verify_area(type, file, pos, tot_len);
 	if (ret < 0)
 		goto out;
diff -druNp linux-libre-3.8-gnu1/fs/dcache.c linux-libre-3.8.13-gnu1/fs/dcache.c
--- linux-libre-3.8-gnu1/fs/dcache.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/dcache.c	2013-05-11 16:57:46.000000000 -0400
@@ -1232,8 +1232,10 @@ void shrink_dcache_parent(struct dentry
 	LIST_HEAD(dispose);
 	int found;
 
-	while ((found = select_parent(parent, &dispose)) != 0)
+	while ((found = select_parent(parent, &dispose)) != 0) {
 		shrink_dentry_list(&dispose);
+		cond_resched();
+	}
 }
 EXPORT_SYMBOL(shrink_dcache_parent);
 
@@ -2552,7 +2554,6 @@ static int prepend_path(const struct pat
 	bool slash = false;
 	int error = 0;
 
-	br_read_lock(&vfsmount_lock);
 	while (dentry != root->dentry || vfsmnt != root->mnt) {
 		struct dentry * parent;
 
@@ -2582,8 +2583,6 @@ static int prepend_path(const struct pat
 	if (!error && !slash)
 		error = prepend(buffer, buflen, "/", 1);
 
-out:
-	br_read_unlock(&vfsmount_lock);
 	return error;
 
 global_root:
@@ -2600,7 +2599,7 @@ global_root:
 		error = prepend(buffer, buflen, "/", 1);
 	if (!error)
 		error = is_mounted(vfsmnt) ? 1 : 2;
-	goto out;
+	return error;
 }
 
 /**
@@ -2627,9 +2626,11 @@ char *__d_path(const struct path *path,
 	int error;
 
 	prepend(&res, &buflen, "\0", 1);
+	br_read_lock(&vfsmount_lock);
 	write_seqlock(&rename_lock);
 	error = prepend_path(path, root, &res, &buflen);
 	write_sequnlock(&rename_lock);
+	br_read_unlock(&vfsmount_lock);
 
 	if (error < 0)
 		return ERR_PTR(error);
@@ -2646,9 +2647,11 @@ char *d_absolute_path(const struct path
 	int error;
 
 	prepend(&res, &buflen, "\0", 1);
+	br_read_lock(&vfsmount_lock);
 	write_seqlock(&rename_lock);
 	error = prepend_path(path, &root, &res, &buflen);
 	write_sequnlock(&rename_lock);
+	br_read_unlock(&vfsmount_lock);
 
 	if (error > 1)
 		error = -EINVAL;
@@ -2712,11 +2715,13 @@ char *d_path(const struct path *path, ch
 		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
 	get_fs_root(current->fs, &root);
+	br_read_lock(&vfsmount_lock);
 	write_seqlock(&rename_lock);
 	error = path_with_deleted(path, &root, &res, &buflen);
+	write_sequnlock(&rename_lock);
+	br_read_unlock(&vfsmount_lock);
 	if (error < 0)
 		res = ERR_PTR(error);
-	write_sequnlock(&rename_lock);
 	path_put(&root);
 	return res;
 }
@@ -2871,6 +2876,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
 	get_fs_root_and_pwd(current->fs, &root, &pwd);
 
 	error = -ENOENT;
+	br_read_lock(&vfsmount_lock);
 	write_seqlock(&rename_lock);
 	if (!d_unlinked(pwd.dentry)) {
 		unsigned long len;
@@ -2880,6 +2886,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
 		prepend(&cwd, &buflen, "\0", 1);
 		error = prepend_path(&pwd, &root, &cwd, &buflen);
 		write_sequnlock(&rename_lock);
+		br_read_unlock(&vfsmount_lock);
 
 		if (error < 0)
 			goto out;
@@ -2900,6 +2907,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
 		}
 	} else {
 		write_sequnlock(&rename_lock);
+		br_read_unlock(&vfsmount_lock);
 	}
 
 out:
diff -druNp linux-libre-3.8-gnu1/fs/direct-io.c linux-libre-3.8.13-gnu1/fs/direct-io.c
--- linux-libre-3.8-gnu1/fs/direct-io.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/direct-io.c	2013-05-11 16:57:46.000000000 -0400
@@ -261,9 +261,9 @@ static ssize_t dio_complete(struct dio *
 		dio->end_io(dio->iocb, offset, transferred,
 			    dio->private, ret, is_async);
 	} else {
+		inode_dio_done(dio->inode);
 		if (is_async)
 			aio_complete(dio->iocb, ret, 0);
-		inode_dio_done(dio->inode);
 	}
 
 	return ret;
diff -druNp linux-libre-3.8-gnu1/fs/exec.c linux-libre-3.8.13-gnu1/fs/exec.c
--- linux-libre-3.8-gnu1/fs/exec.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/exec.c	2013-05-11 16:57:46.000000000 -0400
@@ -613,7 +613,7 @@ static int shift_arg_pages(struct vm_are
 		 * when the old and new regions overlap clear from new_end.
 		 */
 		free_pgd_range(&tlb, new_end, old_end, new_end,
-			vma->vm_next ? vma->vm_next->vm_start : 0);
+			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
 	} else {
 		/*
 		 * otherwise, clean from old_start; this is done to not touch
@@ -622,7 +622,7 @@ static int shift_arg_pages(struct vm_are
 		 * for the others its just a little faster.
 		 */
 		free_pgd_range(&tlb, old_start, old_end, new_end,
-			vma->vm_next ? vma->vm_next->vm_start : 0);
+			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
 	}
 	tlb_finish_mmu(&tlb, new_end, old_end);
 
@@ -898,11 +898,13 @@ static int de_thread(struct task_struct
 
 		sig->notify_count = -1;	/* for exit_notify() */
 		for (;;) {
+			threadgroup_change_begin(tsk);
 			write_lock_irq(&tasklist_lock);
 			if (likely(leader->exit_state))
 				break;
 			__set_current_state(TASK_KILLABLE);
 			write_unlock_irq(&tasklist_lock);
+			threadgroup_change_end(tsk);
 			schedule();
 			if (unlikely(__fatal_signal_pending(tsk)))
 				goto killed;
@@ -960,6 +962,7 @@ static int de_thread(struct task_struct
 		if (unlikely(leader->ptrace))
 			__wake_up_parent(leader, leader->parent);
 		write_unlock_irq(&tasklist_lock);
+		threadgroup_change_end(tsk);
 
 		release_task(leader);
 	}
diff -druNp linux-libre-3.8-gnu1/fs/ext3/super.c linux-libre-3.8.13-gnu1/fs/ext3/super.c
--- linux-libre-3.8-gnu1/fs/ext3/super.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext3/super.c	2013-05-11 16:57:46.000000000 -0400
@@ -353,7 +353,7 @@ static struct block_device *ext3_blkdev_
 	return bdev;
 
 fail:
-	ext3_msg(sb, "error: failed to open journal device %s: %ld",
+	ext3_msg(sb, KERN_ERR, "error: failed to open journal device %s: %ld",
 		__bdevname(dev, b), PTR_ERR(bdev));
 
 	return NULL;
@@ -887,7 +887,7 @@ static ext3_fsblk_t get_sb_block(void **
 	/*todo: use simple_strtoll with >32bit ext3 */
 	sb_block = simple_strtoul(options, &options, 0);
 	if (*options && *options != ',') {
-		ext3_msg(sb, "error: invalid sb specification: %s",
+		ext3_msg(sb, KERN_ERR, "error: invalid sb specification: %s",
 		       (char *) *data);
 		return 1;
 	}
diff -druNp linux-libre-3.8-gnu1/fs/ext4/balloc.c linux-libre-3.8.13-gnu1/fs/ext4/balloc.c
--- linux-libre-3.8-gnu1/fs/ext4/balloc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/balloc.c	2013-05-11 16:57:46.000000000 -0400
@@ -358,7 +358,7 @@ void ext4_validate_block_bitmap(struct s
 }
 
 /**
- * ext4_read_block_bitmap()
+ * ext4_read_block_bitmap_nowait()
  * @sb:			super block
  * @block_group:	given block group
  *
@@ -457,6 +457,8 @@ ext4_read_block_bitmap(struct super_bloc
 	struct buffer_head *bh;
 
 	bh = ext4_read_block_bitmap_nowait(sb, block_group);
+	if (!bh)
+		return NULL;
 	if (ext4_wait_block_bitmap(sb, block_group, bh)) {
 		put_bh(bh);
 		return NULL;
@@ -482,11 +484,16 @@ static int ext4_has_free_clusters(struct
 
 	free_clusters  = percpu_counter_read_positive(fcc);
 	dirty_clusters = percpu_counter_read_positive(dcc);
-	root_clusters = EXT4_B2C(sbi, ext4_r_blocks_count(sbi->s_es));
+
+	/*
+	 * r_blocks_count should always be multiple of the cluster ratio so
+	 * we are safe to do a plane bit shift only.
+	 */
+	root_clusters = ext4_r_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
 
 	if (free_clusters - (nclusters + root_clusters + dirty_clusters) <
 					EXT4_FREECLUSTERS_WATERMARK) {
-		free_clusters  = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc));
+		free_clusters  = percpu_counter_sum_positive(fcc);
 		dirty_clusters = percpu_counter_sum_positive(dcc);
 	}
 	/* Check whether we have space after accounting for current
@@ -628,7 +635,7 @@ ext4_fsblk_t ext4_count_free_clusters(st
 	brelse(bitmap_bh);
 	printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"
 	       ", computed = %llu, %llu\n",
-	       EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)),
+	       EXT4_NUM_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)),
 	       desc_count, bitmap_count);
 	return bitmap_count;
 #else
diff -druNp linux-libre-3.8-gnu1/fs/ext4/ext4.h linux-libre-3.8.13-gnu1/fs/ext4/ext4.h
--- linux-libre-3.8-gnu1/fs/ext4/ext4.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/ext4.h	2013-05-11 16:57:46.000000000 -0400
@@ -338,9 +338,9 @@ struct ext4_group_desc
  */
 
 struct flex_groups {
-	atomic_t free_inodes;
-	atomic_t free_clusters;
-	atomic_t used_dirs;
+	atomic64_t	free_clusters;
+	atomic_t	free_inodes;
+	atomic_t	used_dirs;
 };
 
 #define EXT4_BG_INODE_UNINIT	0x0001 /* Inode table/bitmap not in use */
diff -druNp linux-libre-3.8-gnu1/fs/ext4/ext4_jbd2.h linux-libre-3.8.13-gnu1/fs/ext4/ext4_jbd2.h
--- linux-libre-3.8-gnu1/fs/ext4/ext4_jbd2.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/ext4_jbd2.h	2013-05-11 16:57:46.000000000 -0400
@@ -170,16 +170,20 @@ static inline void ext4_journal_callback
  * ext4_journal_callback_del: delete a registered callback
  * @handle: active journal transaction handle on which callback was registered
  * @jce: registered journal callback entry to unregister
+ * Return true if object was sucessfully removed
  */
-static inline void ext4_journal_callback_del(handle_t *handle,
+static inline bool ext4_journal_callback_try_del(handle_t *handle,
 					     struct ext4_journal_cb_entry *jce)
 {
+	bool deleted;
 	struct ext4_sb_info *sbi =
 			EXT4_SB(handle->h_transaction->t_journal->j_private);
 
 	spin_lock(&sbi->s_md_lock);
+	deleted = !list_empty(&jce->jce_list);
 	list_del_init(&jce->jce_list);
 	spin_unlock(&sbi->s_md_lock);
+	return deleted;
 }
 
 int
diff -druNp linux-libre-3.8-gnu1/fs/ext4/extents.c linux-libre-3.8.13-gnu1/fs/ext4/extents.c
--- linux-libre-3.8-gnu1/fs/ext4/extents.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/extents.c	2013-05-11 16:57:46.000000000 -0400
@@ -725,6 +725,7 @@ ext4_ext_find_extent(struct inode *inode
 	struct ext4_extent_header *eh;
 	struct buffer_head *bh;
 	short int depth, i, ppos = 0, alloc = 0;
+	int ret;
 
 	eh = ext_inode_hdr(inode);
 	depth = ext_depth(inode);
@@ -752,12 +753,15 @@ ext4_ext_find_extent(struct inode *inode
 		path[ppos].p_ext = NULL;
 
 		bh = sb_getblk(inode->i_sb, path[ppos].p_block);
-		if (unlikely(!bh))
+		if (unlikely(!bh)) {
+			ret = -ENOMEM;
 			goto err;
+		}
 		if (!bh_uptodate_or_lock(bh)) {
 			trace_ext4_ext_load_extent(inode, block,
 						path[ppos].p_block);
-			if (bh_submit_read(bh) < 0) {
+			ret = bh_submit_read(bh);
+			if (ret < 0) {
 				put_bh(bh);
 				goto err;
 			}
@@ -768,13 +772,15 @@ ext4_ext_find_extent(struct inode *inode
 			put_bh(bh);
 			EXT4_ERROR_INODE(inode,
 					 "ppos %d > depth %d", ppos, depth);
+			ret = -EIO;
 			goto err;
 		}
 		path[ppos].p_bh = bh;
 		path[ppos].p_hdr = eh;
 		i--;
 
-		if (ext4_ext_check_block(inode, eh, i, bh))
+		ret = ext4_ext_check_block(inode, eh, i, bh);
+		if (ret < 0)
 			goto err;
 	}
 
@@ -796,7 +802,7 @@ err:
 	ext4_ext_drop_refs(path);
 	if (alloc)
 		kfree(path);
-	return ERR_PTR(-EIO);
+	return ERR_PTR(ret);
 }
 
 /*
@@ -951,7 +957,7 @@ static int ext4_ext_split(handle_t *hand
 	}
 	bh = sb_getblk(inode->i_sb, newblock);
 	if (!bh) {
-		err = -EIO;
+		err = -ENOMEM;
 		goto cleanup;
 	}
 	lock_buffer(bh);
@@ -1024,7 +1030,7 @@ static int ext4_ext_split(handle_t *hand
 		newblock = ablocks[--a];
 		bh = sb_getblk(inode->i_sb, newblock);
 		if (!bh) {
-			err = -EIO;
+			err = -ENOMEM;
 			goto cleanup;
 		}
 		lock_buffer(bh);
@@ -1136,11 +1142,8 @@ static int ext4_ext_grow_indepth(handle_
 		return err;
 
 	bh = sb_getblk(inode->i_sb, newblock);
-	if (!bh) {
-		err = -EIO;
-		ext4_std_error(inode->i_sb, err);
-		return err;
-	}
+	if (!bh)
+		return -ENOMEM;
 	lock_buffer(bh);
 
 	err = ext4_journal_get_create_access(handle, bh);
@@ -3086,6 +3089,7 @@ static int ext4_split_extent(handle_t *h
 	int err = 0;
 	int uninitialized;
 	int split_flag1, flags1;
+	int allocated = map->m_len;
 
 	depth = ext_depth(inode);
 	ex = path[depth].p_ext;
@@ -3105,6 +3109,8 @@ static int ext4_split_extent(handle_t *h
 				map->m_lblk + map->m_len, split_flag1, flags1);
 		if (err)
 			goto out;
+	} else {
+		allocated = ee_len - (map->m_lblk - ee_block);
 	}
 
 	ext4_ext_drop_refs(path);
@@ -3127,7 +3133,7 @@ static int ext4_split_extent(handle_t *h
 
 	ext4_ext_show_leaf(inode, path);
 out:
-	return err ? err : map->m_len;
+	return err ? err : allocated;
 }
 
 /*
@@ -3272,7 +3278,7 @@ static int ext4_ext_convert_to_initializ
 
 	if (EXT4_EXT_MAY_ZEROOUT & split_flag)
 		max_zeroout = sbi->s_extent_max_zeroout_kb >>
-			inode->i_sb->s_blocksize_bits;
+			(inode->i_sb->s_blocksize_bits - 10);
 
 	/* If extent is less than s_max_zeroout_kb, zeroout directly */
 	if (max_zeroout && (ee_len <= max_zeroout)) {
@@ -3717,6 +3723,7 @@ out:
 					allocated - map->m_len);
 		allocated = map->m_len;
 	}
+	map->m_len = allocated;
 
 	/*
 	 * If we have done fallocate with the offset that is already
diff -druNp linux-libre-3.8-gnu1/fs/ext4/fsync.c linux-libre-3.8.13-gnu1/fs/ext4/fsync.c
--- linux-libre-3.8-gnu1/fs/ext4/fsync.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/fsync.c	2013-05-11 16:57:46.000000000 -0400
@@ -166,8 +166,7 @@ int ext4_sync_file(struct file *file, lo
 	if (journal->j_flags & JBD2_BARRIER &&
 	    !jbd2_trans_will_send_data_barrier(journal, commit_tid))
 		needs_barrier = true;
-	jbd2_log_start_commit(journal, commit_tid);
-	ret = jbd2_log_wait_commit(journal, commit_tid);
+	ret = jbd2_complete_transaction(journal, commit_tid);
 	if (needs_barrier) {
 		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 		if (!ret)
diff -druNp linux-libre-3.8-gnu1/fs/ext4/ialloc.c linux-libre-3.8.13-gnu1/fs/ext4/ialloc.c
--- linux-libre-3.8-gnu1/fs/ext4/ialloc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/ialloc.c	2013-05-11 16:57:46.000000000 -0400
@@ -324,8 +324,8 @@ error_return:
 }
 
 struct orlov_stats {
+	__u64 free_clusters;
 	__u32 free_inodes;
-	__u32 free_clusters;
 	__u32 used_dirs;
 };
 
@@ -342,7 +342,7 @@ static void get_orlov_stats(struct super
 
 	if (flex_size > 1) {
 		stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
-		stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
+		stats->free_clusters = atomic64_read(&flex_group[g].free_clusters);
 		stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
 		return;
 	}
diff -druNp linux-libre-3.8-gnu1/fs/ext4/indirect.c linux-libre-3.8.13-gnu1/fs/ext4/indirect.c
--- linux-libre-3.8-gnu1/fs/ext4/indirect.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/indirect.c	2013-05-11 16:57:46.000000000 -0400
@@ -146,6 +146,7 @@ static Indirect *ext4_get_branch(struct
 	struct super_block *sb = inode->i_sb;
 	Indirect *p = chain;
 	struct buffer_head *bh;
+	int ret = -EIO;
 
 	*err = 0;
 	/* i_data is not going away, no lock needed */
@@ -154,8 +155,10 @@ static Indirect *ext4_get_branch(struct
 		goto no_block;
 	while (--depth) {
 		bh = sb_getblk(sb, le32_to_cpu(p->key));
-		if (unlikely(!bh))
+		if (unlikely(!bh)) {
+			ret = -ENOMEM;
 			goto failure;
+		}
 
 		if (!bh_uptodate_or_lock(bh)) {
 			if (bh_submit_read(bh) < 0) {
@@ -177,7 +180,7 @@ static Indirect *ext4_get_branch(struct
 	return NULL;
 
 failure:
-	*err = -EIO;
+	*err = ret;
 no_block:
 	return p;
 }
@@ -471,7 +474,7 @@ static int ext4_alloc_branch(handle_t *h
 		 */
 		bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
 		if (unlikely(!bh)) {
-			err = -EIO;
+			err = -ENOMEM;
 			goto failed;
 		}
 
diff -druNp linux-libre-3.8-gnu1/fs/ext4/inline.c linux-libre-3.8.13-gnu1/fs/ext4/inline.c
--- linux-libre-3.8-gnu1/fs/ext4/inline.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/inline.c	2013-05-11 16:57:46.000000000 -0400
@@ -1188,7 +1188,7 @@ static int ext4_convert_inline_data_nolo
 
 	data_bh = sb_getblk(inode->i_sb, map.m_pblk);
 	if (!data_bh) {
-		error = -EIO;
+		error = -ENOMEM;
 		goto out_restore;
 	}
 
diff -druNp linux-libre-3.8-gnu1/fs/ext4/inode.c linux-libre-3.8.13-gnu1/fs/ext4/inode.c
--- linux-libre-3.8-gnu1/fs/ext4/inode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/inode.c	2013-05-11 16:57:46.000000000 -0400
@@ -55,21 +55,21 @@ static __u32 ext4_inode_csum(struct inod
 	__u16 csum_hi = 0;
 	__u32 csum;
 
-	csum_lo = raw->i_checksum_lo;
+	csum_lo = le16_to_cpu(raw->i_checksum_lo);
 	raw->i_checksum_lo = 0;
 	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
 	    EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {
-		csum_hi = raw->i_checksum_hi;
+		csum_hi = le16_to_cpu(raw->i_checksum_hi);
 		raw->i_checksum_hi = 0;
 	}
 
 	csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw,
 			   EXT4_INODE_SIZE(inode->i_sb));
 
-	raw->i_checksum_lo = csum_lo;
+	raw->i_checksum_lo = cpu_to_le16(csum_lo);
 	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
 	    EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))
-		raw->i_checksum_hi = csum_hi;
+		raw->i_checksum_hi = cpu_to_le16(csum_hi);
 
 	return csum;
 }
@@ -211,12 +211,12 @@ void ext4_evict_inode(struct inode *inod
 		 * don't use page cache.
 		 */
 		if (ext4_should_journal_data(inode) &&
-		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
+		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
+		    inode->i_ino != EXT4_JOURNAL_INO) {
 			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
 			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
 
-			jbd2_log_start_commit(journal, commit_tid);
-			jbd2_log_wait_commit(journal, commit_tid);
+			jbd2_complete_transaction(journal, commit_tid);
 			filemap_write_and_wait(&inode->i_data);
 		}
 		truncate_inode_pages(&inode->i_data, 0);
@@ -714,7 +714,7 @@ struct buffer_head *ext4_getblk(handle_t
 
 	bh = sb_getblk(inode->i_sb, map.m_pblk);
 	if (!bh) {
-		*errp = -EIO;
+		*errp = -ENOMEM;
 		return NULL;
 	}
 	if (map.m_flags & EXT4_MAP_NEW) {
@@ -2977,9 +2977,9 @@ static void ext4_end_io_dio(struct kiocb
 	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
 		ext4_free_io_end(io_end);
 out:
+		inode_dio_done(inode);
 		if (is_async)
 			aio_complete(iocb, ret, 0);
-		inode_dio_done(inode);
 		return;
 	}
 
@@ -3660,11 +3660,8 @@ static int __ext4_get_inode_loc(struct i
 	iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
 
 	bh = sb_getblk(sb, block);
-	if (!bh) {
-		EXT4_ERROR_INODE_BLOCK(inode, block,
-				       "unable to read itable block");
-		return -EIO;
-	}
+	if (!bh)
+		return -ENOMEM;
 	if (!buffer_uptodate(bh)) {
 		lock_buffer(bh);
 
diff -druNp linux-libre-3.8-gnu1/fs/ext4/Kconfig linux-libre-3.8.13-gnu1/fs/ext4/Kconfig
--- linux-libre-3.8-gnu1/fs/ext4/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -71,4 +71,5 @@ config EXT4_DEBUG
 	  Enables run-time debugging support for the ext4 filesystem.
 
 	  If you select Y here, then you will be able to turn on debugging
-	  with a command such as "echo 1 > /sys/kernel/debug/ext4/mballoc-debug"
+	  with a command such as:
+		echo 1 > /sys/module/ext4/parameters/mballoc_debug
diff -druNp linux-libre-3.8-gnu1/fs/ext4/mballoc.c linux-libre-3.8.13-gnu1/fs/ext4/mballoc.c
--- linux-libre-3.8-gnu1/fs/ext4/mballoc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/mballoc.c	2013-05-11 16:57:46.000000000 -0400
@@ -2829,8 +2829,8 @@ ext4_mb_mark_diskspace_used(struct ext4_
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi,
 							  ac->ac_b_ex.fe_group);
-		atomic_sub(ac->ac_b_ex.fe_len,
-			   &sbi->s_flex_groups[flex_group].free_clusters);
+		atomic64_sub(ac->ac_b_ex.fe_len,
+			     &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -3444,7 +3444,7 @@ ext4_mb_new_inode_pa(struct ext4_allocat
 			win = offs;
 
 		ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical -
-			EXT4_B2C(sbi, win);
+			EXT4_NUM_B2C(sbi, win);
 		BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
 		BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
 	}
@@ -4136,7 +4136,7 @@ static void ext4_mb_add_n_trim(struct ex
 		/* The max size of hash table is PREALLOC_TB_SIZE */
 		order = PREALLOC_TB_SIZE - 1;
 	/* Add the prealloc space to lg */
-	rcu_read_lock();
+	spin_lock(&lg->lg_prealloc_lock);
 	list_for_each_entry_rcu(tmp_pa, &lg->lg_prealloc_list[order],
 						pa_inode_list) {
 		spin_lock(&tmp_pa->pa_lock);
@@ -4160,12 +4160,12 @@ static void ext4_mb_add_n_trim(struct ex
 	if (!added)
 		list_add_tail_rcu(&pa->pa_inode_list,
 					&lg->lg_prealloc_list[order]);
-	rcu_read_unlock();
+	spin_unlock(&lg->lg_prealloc_lock);
 
 	/* Now trim the list to be not more than 8 elements */
 	if (lg_prealloc_count > 8) {
 		ext4_mb_discard_lg_preallocations(sb, lg,
-						order, lg_prealloc_count);
+						  order, lg_prealloc_count);
 		return;
 	}
 	return ;
@@ -4449,11 +4449,11 @@ ext4_mb_free_metadata(handle_t *handle,
 	node = rb_prev(new_node);
 	if (node) {
 		entry = rb_entry(node, struct ext4_free_data, efd_node);
-		if (can_merge(entry, new_entry)) {
+		if (can_merge(entry, new_entry) &&
+		    ext4_journal_callback_try_del(handle, &entry->efd_jce)) {
 			new_entry->efd_start_cluster = entry->efd_start_cluster;
 			new_entry->efd_count += entry->efd_count;
 			rb_erase(node, &(db->bb_free_root));
-			ext4_journal_callback_del(handle, &entry->efd_jce);
 			kmem_cache_free(ext4_free_data_cachep, entry);
 		}
 	}
@@ -4461,10 +4461,10 @@ ext4_mb_free_metadata(handle_t *handle,
 	node = rb_next(new_node);
 	if (node) {
 		entry = rb_entry(node, struct ext4_free_data, efd_node);
-		if (can_merge(new_entry, entry)) {
+		if (can_merge(new_entry, entry) &&
+		    ext4_journal_callback_try_del(handle, &entry->efd_jce)) {
 			new_entry->efd_count += entry->efd_count;
 			rb_erase(node, &(db->bb_free_root));
-			ext4_journal_callback_del(handle, &entry->efd_jce);
 			kmem_cache_free(ext4_free_data_cachep, entry);
 		}
 	}
@@ -4590,7 +4590,7 @@ do_more:
 			EXT4_BLOCKS_PER_GROUP(sb);
 		count -= overflow;
 	}
-	count_clusters = EXT4_B2C(sbi, count);
+	count_clusters = EXT4_NUM_B2C(sbi, count);
 	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
 	if (!bitmap_bh) {
 		err = -EIO;
@@ -4691,8 +4691,8 @@ do_more:
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-		atomic_add(count_clusters,
-			   &sbi->s_flex_groups[flex_group].free_clusters);
+		atomic64_add(count_clusters,
+			     &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
 	ext4_mb_unload_buddy(&e4b);
@@ -4832,12 +4832,12 @@ int ext4_group_add_blocks(handle_t *hand
 	ext4_group_desc_csum_set(sb, block_group, desc);
 	ext4_unlock_group(sb, block_group);
 	percpu_counter_add(&sbi->s_freeclusters_counter,
-			   EXT4_B2C(sbi, blocks_freed));
+			   EXT4_NUM_B2C(sbi, blocks_freed));
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-		atomic_add(EXT4_B2C(sbi, blocks_freed),
-			   &sbi->s_flex_groups[flex_group].free_clusters);
+		atomic64_add(EXT4_NUM_B2C(sbi, blocks_freed),
+			     &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
 	ext4_mb_unload_buddy(&e4b);
diff -druNp linux-libre-3.8-gnu1/fs/ext4/mmp.c linux-libre-3.8.13-gnu1/fs/ext4/mmp.c
--- linux-libre-3.8-gnu1/fs/ext4/mmp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/mmp.c	2013-05-11 16:57:46.000000000 -0400
@@ -7,7 +7,7 @@
 #include "ext4.h"
 
 /* Checksumming functions */
-static __u32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp)
+static __le32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	int offset = offsetof(struct mmp_struct, mmp_checksum);
@@ -80,6 +80,8 @@ static int read_mmp_block(struct super_b
 	 * is not blocked in the elevator. */
 	if (!*bh)
 		*bh = sb_getblk(sb, mmp_block);
+	if (!*bh)
+		return -ENOMEM;
 	if (*bh) {
 		get_bh(*bh);
 		lock_buffer(*bh);
diff -druNp linux-libre-3.8-gnu1/fs/ext4/page-io.c linux-libre-3.8.13-gnu1/fs/ext4/page-io.c
--- linux-libre-3.8-gnu1/fs/ext4/page-io.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/page-io.c	2013-05-11 16:57:46.000000000 -0400
@@ -103,14 +103,13 @@ static int ext4_end_io(ext4_io_end_t *io
 			 "(inode %lu, offset %llu, size %zd, error %d)",
 			 inode->i_ino, offset, size, ret);
 	}
-	if (io->iocb)
-		aio_complete(io->iocb, io->result, 0);
-
-	if (io->flag & EXT4_IO_END_DIRECT)
-		inode_dio_done(inode);
 	/* Wake up anyone waiting on unwritten extent conversion */
 	if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
 		wake_up_all(ext4_ioend_wq(inode));
+	if (io->flag & EXT4_IO_END_DIRECT)
+		inode_dio_done(inode);
+	if (io->iocb)
+		aio_complete(io->iocb, io->result, 0);
 	return ret;
 }
 
diff -druNp linux-libre-3.8-gnu1/fs/ext4/resize.c linux-libre-3.8.13-gnu1/fs/ext4/resize.c
--- linux-libre-3.8-gnu1/fs/ext4/resize.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/resize.c	2013-05-11 16:57:46.000000000 -0400
@@ -334,7 +334,7 @@ static struct buffer_head *bclean(handle
 
 	bh = sb_getblk(sb, blk);
 	if (!bh)
-		return ERR_PTR(-EIO);
+		return ERR_PTR(-ENOMEM);
 	if ((err = ext4_journal_get_write_access(handle, bh))) {
 		brelse(bh);
 		bh = ERR_PTR(err);
@@ -411,7 +411,7 @@ static int set_flexbg_block_bitmap(struc
 
 		bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap);
 		if (!bh)
-			return -EIO;
+			return -ENOMEM;
 
 		err = ext4_journal_get_write_access(handle, bh);
 		if (err)
@@ -501,7 +501,7 @@ static int setup_new_flex_group_blocks(s
 
 			gdb = sb_getblk(sb, block);
 			if (!gdb) {
-				err = -EIO;
+				err = -ENOMEM;
 				goto out;
 			}
 
@@ -1065,7 +1065,7 @@ static void update_backups(struct super_
 
 		bh = sb_getblk(sb, backup_block);
 		if (!bh) {
-			err = -EIO;
+			err = -ENOMEM;
 			break;
 		}
 		ext4_debug("update metadata backup %llu(+%llu)\n",
@@ -1247,7 +1247,7 @@ static int ext4_setup_new_descs(handle_t
 
 		ext4_inode_table_set(sb, gdp, group_data->inode_table);
 		ext4_free_group_clusters_set(sb, gdp,
-					     EXT4_B2C(sbi, group_data->free_blocks_count));
+			EXT4_NUM_B2C(sbi, group_data->free_blocks_count));
 		ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
 		if (ext4_has_group_desc_csum(sb))
 			ext4_itable_unused_set(sb, gdp,
@@ -1341,6 +1341,8 @@ static void ext4_update_super(struct sup
 
 	/* Update the global fs size fields */
 	sbi->s_groups_count += flex_gd->count;
+	sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
+			(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
 
 	/* Update the reserved block counts only once the new group is
 	 * active. */
@@ -1349,7 +1351,7 @@ static void ext4_update_super(struct sup
 
 	/* Update the free space counts */
 	percpu_counter_add(&sbi->s_freeclusters_counter,
-			   EXT4_B2C(sbi, free_blocks));
+			   EXT4_NUM_B2C(sbi, free_blocks));
 	percpu_counter_add(&sbi->s_freeinodes_counter,
 			   EXT4_INODES_PER_GROUP(sb) * flex_gd->count);
 
@@ -1360,8 +1362,8 @@ static void ext4_update_super(struct sup
 	    sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group;
 		flex_group = ext4_flex_group(sbi, group_data[0].group);
-		atomic_add(EXT4_B2C(sbi, free_blocks),
-			   &sbi->s_flex_groups[flex_group].free_clusters);
+		atomic64_add(EXT4_NUM_B2C(sbi, free_blocks),
+			     &sbi->s_flex_groups[flex_group].free_clusters);
 		atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,
 			   &sbi->s_flex_groups[flex_group].free_inodes);
 	}
@@ -1878,6 +1880,10 @@ retry:
 		return 0;
 
 	ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset);
+	if (n_group > (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) {
+		ext4_warning(sb, "resize would cause inodes_count overflow");
+		return -EINVAL;
+	}
 	ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset);
 
 	n_desc_blocks = num_desc_blocks(sb, n_group + 1);
diff -druNp linux-libre-3.8-gnu1/fs/ext4/super.c linux-libre-3.8.13-gnu1/fs/ext4/super.c
--- linux-libre-3.8-gnu1/fs/ext4/super.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/super.c	2013-05-11 16:57:46.000000000 -0400
@@ -452,10 +452,13 @@ static void ext4_journal_commit_callback
 	struct super_block		*sb = journal->j_private;
 	struct ext4_sb_info		*sbi = EXT4_SB(sb);
 	int				error = is_journal_aborted(journal);
-	struct ext4_journal_cb_entry	*jce, *tmp;
+	struct ext4_journal_cb_entry	*jce;
 
+	BUG_ON(txn->t_state == T_FINISHED);
 	spin_lock(&sbi->s_md_lock);
-	list_for_each_entry_safe(jce, tmp, &txn->t_private_list, jce_list) {
+	while (!list_empty(&txn->t_private_list)) {
+		jce = list_entry(txn->t_private_list.next,
+				 struct ext4_journal_cb_entry, jce_list);
 		list_del_init(&jce->jce_list);
 		spin_unlock(&sbi->s_md_lock);
 		jce->jce_func(sb, jce, error);
@@ -1979,8 +1982,8 @@ static int ext4_fill_flex_info(struct su
 		flex_group = ext4_flex_group(sbi, i);
 		atomic_add(ext4_free_inodes_count(sb, gdp),
 			   &sbi->s_flex_groups[flex_group].free_inodes);
-		atomic_add(ext4_free_group_clusters(sb, gdp),
-			   &sbi->s_flex_groups[flex_group].free_clusters);
+		atomic64_add(ext4_free_group_clusters(sb, gdp),
+			     &sbi->s_flex_groups[flex_group].free_clusters);
 		atomic_add(ext4_used_dirs_count(sb, gdp),
 			   &sbi->s_flex_groups[flex_group].used_dirs);
 	}
@@ -3235,7 +3238,7 @@ int ext4_calculate_overhead(struct super
 	}
 	/* Add the journal blocks as well */
 	if (sbi->s_journal)
-		overhead += EXT4_B2C(sbi, sbi->s_journal->j_maxlen);
+		overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen);
 
 	sbi->s_overhead = overhead;
 	smp_wmb();
@@ -4008,7 +4011,7 @@ no_journal:
 	    !(sb->s_flags & MS_RDONLY)) {
 		err = ext4_enable_quotas(sb);
 		if (err)
-			goto failed_mount7;
+			goto failed_mount8;
 	}
 #endif  /* CONFIG_QUOTA */
 
@@ -4035,6 +4038,10 @@ cantfind_ext4:
 		ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
 	goto failed_mount;
 
+#ifdef CONFIG_QUOTA
+failed_mount8:
+	kobject_del(&sbi->s_kobj);
+#endif
 failed_mount7:
 	ext4_unregister_li_request(sb);
 failed_mount6:
@@ -5005,9 +5012,9 @@ static int ext4_enable_quotas(struct sup
 						DQUOT_USAGE_ENABLED);
 			if (err) {
 				ext4_warning(sb,
-					"Failed to enable quota (type=%d) "
-					"tracking. Please run e2fsck to fix.",
-					type);
+					"Failed to enable quota tracking "
+					"(type=%d, err=%d). Please run "
+					"e2fsck to fix.", type, err);
 				return err;
 			}
 		}
diff -druNp linux-libre-3.8-gnu1/fs/ext4/xattr.c linux-libre-3.8.13-gnu1/fs/ext4/xattr.c
--- linux-libre-3.8-gnu1/fs/ext4/xattr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ext4/xattr.c	2013-05-11 16:57:46.000000000 -0400
@@ -549,7 +549,7 @@ ext4_xattr_release_block(handle_t *handl
 		error = ext4_handle_dirty_xattr_block(handle, inode, bh);
 		if (IS_SYNC(inode))
 			ext4_handle_sync(handle);
-		dquot_free_block(inode, 1);
+		dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
 		ea_bdebug(bh, "refcount now=%d; releasing",
 			  le32_to_cpu(BHDR(bh)->h_refcount));
 	}
@@ -832,7 +832,8 @@ inserted:
 			else {
 				/* The old block is released after updating
 				   the inode. */
-				error = dquot_alloc_block(inode, 1);
+				error = dquot_alloc_block(inode,
+						EXT4_C2B(EXT4_SB(sb), 1));
 				if (error)
 					goto cleanup;
 				error = ext4_journal_get_write_access(handle,
@@ -887,16 +888,17 @@ inserted:
 
 			new_bh = sb_getblk(sb, block);
 			if (!new_bh) {
+				error = -ENOMEM;
 getblk_failed:
 				ext4_free_blocks(handle, inode, NULL, block, 1,
 						 EXT4_FREE_BLOCKS_METADATA);
-				error = -EIO;
 				goto cleanup;
 			}
 			lock_buffer(new_bh);
 			error = ext4_journal_get_create_access(handle, new_bh);
 			if (error) {
 				unlock_buffer(new_bh);
+				error = -EIO;
 				goto getblk_failed;
 			}
 			memcpy(new_bh->b_data, s->base, new_bh->b_size);
@@ -928,7 +930,7 @@ cleanup:
 	return error;
 
 cleanup_dquot:
-	dquot_free_block(inode, 1);
+	dquot_free_block(inode, EXT4_C2B(EXT4_SB(sb), 1));
 	goto cleanup;
 
 bad_block:
diff -druNp linux-libre-3.8-gnu1/fs/fscache/stats.c linux-libre-3.8.13-gnu1/fs/fscache/stats.c
--- linux-libre-3.8-gnu1/fs/fscache/stats.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/fscache/stats.c	2013-05-11 16:57:46.000000000 -0400
@@ -287,5 +287,5 @@ const struct file_operations fscache_sta
 	.open		= fscache_stats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= seq_release,
+	.release        = single_release,
 };
diff -druNp linux-libre-3.8-gnu1/fs/fuse/dir.c linux-libre-3.8.13-gnu1/fs/fuse/dir.c
--- linux-libre-3.8-gnu1/fs/fuse/dir.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/fuse/dir.c	2013-05-11 16:57:46.000000000 -0400
@@ -682,7 +682,14 @@ static int fuse_unlink(struct inode *dir
 
 		spin_lock(&fc->lock);
 		fi->attr_version = ++fc->attr_version;
-		drop_nlink(inode);
+		/*
+		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
+		 * happen if userspace filesystem is careless.  It would be
+		 * difficult to enforce correct nlink usage so just ignore this
+		 * condition here
+		 */
+		if (inode->i_nlink > 0)
+			drop_nlink(inode);
 		spin_unlock(&fc->lock);
 		fuse_invalidate_attr(inode);
 		fuse_invalidate_attr(dir);
diff -druNp linux-libre-3.8-gnu1/fs/gfs2/bmap.c linux-libre-3.8.13-gnu1/fs/gfs2/bmap.c
--- linux-libre-3.8-gnu1/fs/gfs2/bmap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/gfs2/bmap.c	2013-05-11 16:57:46.000000000 -0400
@@ -1286,6 +1286,10 @@ int gfs2_setattr_size(struct inode *inod
 
 	inode_dio_wait(inode);
 
+	ret = gfs2_rs_alloc(GFS2_I(inode));
+	if (ret)
+		return ret;
+
 	oldsize = inode->i_size;
 	if (newsize >= oldsize)
 		return do_grow(inode, newsize);
diff -druNp linux-libre-3.8-gnu1/fs/gfs2/file.c linux-libre-3.8.13-gnu1/fs/gfs2/file.c
--- linux-libre-3.8-gnu1/fs/gfs2/file.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/gfs2/file.c	2013-05-11 16:57:46.000000000 -0400
@@ -924,8 +924,11 @@ static int gfs2_lock(struct file *file,
 		cmd = F_SETLK;
 		fl->fl_type = F_UNLCK;
 	}
-	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
+		if (fl->fl_type == F_UNLCK)
+			posix_lock_file_wait(file, fl);
 		return -EIO;
+	}
 	if (IS_GETLK(cmd))
 		return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
 	else if (fl->fl_type == F_UNLCK)
diff -druNp linux-libre-3.8-gnu1/fs/gfs2/rgrp.c linux-libre-3.8.13-gnu1/fs/gfs2/rgrp.c
--- linux-libre-3.8-gnu1/fs/gfs2/rgrp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/gfs2/rgrp.c	2013-05-11 16:57:46.000000000 -0400
@@ -576,7 +576,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
 	RB_CLEAR_NODE(&ip->i_res->rs_node);
 out:
 	up_write(&ip->i_rw_mutex);
-	return 0;
+	return error;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
diff -druNp linux-libre-3.8-gnu1/fs/hfsplus/extents.c linux-libre-3.8.13-gnu1/fs/hfsplus/extents.c
--- linux-libre-3.8-gnu1/fs/hfsplus/extents.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/hfsplus/extents.c	2013-05-11 16:57:46.000000000 -0400
@@ -533,7 +533,7 @@ void hfsplus_file_truncate(struct inode
 		struct address_space *mapping = inode->i_mapping;
 		struct page *page;
 		void *fsdata;
-		u32 size = inode->i_size;
+		loff_t size = inode->i_size;
 
 		res = pagecache_write_begin(NULL, mapping, size, 0,
 						AOP_FLAG_UNINTERRUPTIBLE,
diff -druNp linux-libre-3.8-gnu1/fs/hugetlbfs/inode.c linux-libre-3.8.13-gnu1/fs/hugetlbfs/inode.c
--- linux-libre-3.8-gnu1/fs/hugetlbfs/inode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/hugetlbfs/inode.c	2013-05-11 16:57:46.000000000 -0400
@@ -110,7 +110,7 @@ static int hugetlbfs_file_mmap(struct fi
 	 * way when do_mmap_pgoff unwinds (may be important on powerpc
 	 * and ia64).
 	 */
-	vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
 	vma->vm_ops = &hugetlb_vm_ops;
 
 	if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
@@ -908,19 +908,19 @@ static int can_do_hugetlb_shm(void)
 
 static int get_hstate_idx(int page_size_log)
 {
-	struct hstate *h;
+	struct hstate *h = hstate_sizelog(page_size_log);
 
-	if (!page_size_log)
-		return default_hstate_idx;
-	h = size_to_hstate(1 << page_size_log);
 	if (!h)
 		return -1;
 	return h - hstates;
 }
 
-struct file *hugetlb_file_setup(const char *name, unsigned long addr,
-				size_t size, vm_flags_t acctflag,
-				struct user_struct **user,
+/*
+ * Note that size should be aligned to proper hugepage size in caller side,
+ * otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
+ */
+struct file *hugetlb_file_setup(const char *name, size_t size,
+				vm_flags_t acctflag, struct user_struct **user,
 				int creat_flags, int page_size_log)
 {
 	int error = -ENOMEM;
@@ -929,8 +929,6 @@ struct file *hugetlb_file_setup(const ch
 	struct path path;
 	struct dentry *root;
 	struct qstr quick_string;
-	struct hstate *hstate;
-	unsigned long num_pages;
 	int hstate_idx;
 
 	hstate_idx = get_hstate_idx(page_size_log);
@@ -969,12 +967,10 @@ struct file *hugetlb_file_setup(const ch
 	if (!inode)
 		goto out_dentry;
 
-	hstate = hstate_inode(inode);
-	size += addr & ~huge_page_mask(hstate);
-	num_pages = ALIGN(size, huge_page_size(hstate)) >>
-			huge_page_shift(hstate);
 	error = -ENOMEM;
-	if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag))
+	if (hugetlb_reserve_pages(inode, 0,
+			size >> huge_page_shift(hstate_inode(inode)), NULL,
+			acctflag))
 		goto out_inode;
 
 	d_instantiate(path.dentry, inode);
diff -druNp linux-libre-3.8-gnu1/fs/inode.c linux-libre-3.8.13-gnu1/fs/inode.c
--- linux-libre-3.8-gnu1/fs/inode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/inode.c	2013-05-11 16:57:46.000000000 -0400
@@ -725,7 +725,7 @@ void prune_icache_sb(struct super_block
 		 * inode to the back of the list so we don't spin on it.
 		 */
 		if (!spin_trylock(&inode->i_lock)) {
-			list_move_tail(&inode->i_lru, &sb->s_inode_lru);
+			list_move(&inode->i_lru, &sb->s_inode_lru);
 			continue;
 		}
 
diff -druNp linux-libre-3.8-gnu1/fs/jbd2/commit.c linux-libre-3.8.13-gnu1/fs/jbd2/commit.c
--- linux-libre-3.8-gnu1/fs/jbd2/commit.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/jbd2/commit.c	2013-05-11 16:57:46.000000000 -0400
@@ -382,7 +382,7 @@ void jbd2_journal_commit_transaction(jou
 	int space_left = 0;
 	int first_tag = 0;
 	int tag_flag;
-	int i, to_free = 0;
+	int i;
 	int tag_bytes = journal_tag_bytes(journal);
 	struct buffer_head *cbh = NULL; /* For transactional checksums */
 	__u32 crc32_sum = ~0;
@@ -1126,7 +1126,7 @@ restart_loop:
 	journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
 	spin_unlock(&journal->j_history_lock);
 
-	commit_transaction->t_state = T_FINISHED;
+	commit_transaction->t_state = T_COMMIT_CALLBACK;
 	J_ASSERT(commit_transaction == journal->j_committing_transaction);
 	journal->j_commit_sequence = commit_transaction->t_tid;
 	journal->j_committing_transaction = NULL;
@@ -1141,38 +1141,44 @@ restart_loop:
 				journal->j_average_commit_time*3) / 4;
 	else
 		journal->j_average_commit_time = commit_time;
+
 	write_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL &&
-	    commit_transaction->t_checkpoint_io_list == NULL) {
-		__jbd2_journal_drop_transaction(journal, commit_transaction);
-		to_free = 1;
+	if (journal->j_checkpoint_transactions == NULL) {
+		journal->j_checkpoint_transactions = commit_transaction;
+		commit_transaction->t_cpnext = commit_transaction;
+		commit_transaction->t_cpprev = commit_transaction;
 	} else {
-		if (journal->j_checkpoint_transactions == NULL) {
-			journal->j_checkpoint_transactions = commit_transaction;
-			commit_transaction->t_cpnext = commit_transaction;
-			commit_transaction->t_cpprev = commit_transaction;
-		} else {
-			commit_transaction->t_cpnext =
-				journal->j_checkpoint_transactions;
-			commit_transaction->t_cpprev =
-				commit_transaction->t_cpnext->t_cpprev;
-			commit_transaction->t_cpnext->t_cpprev =
-				commit_transaction;
-			commit_transaction->t_cpprev->t_cpnext =
+		commit_transaction->t_cpnext =
+			journal->j_checkpoint_transactions;
+		commit_transaction->t_cpprev =
+			commit_transaction->t_cpnext->t_cpprev;
+		commit_transaction->t_cpnext->t_cpprev =
+			commit_transaction;
+		commit_transaction->t_cpprev->t_cpnext =
 				commit_transaction;
-		}
 	}
 	spin_unlock(&journal->j_list_lock);
-
+	/* Drop all spin_locks because commit_callback may be block.
+	 * __journal_remove_checkpoint() can not destroy transaction
+	 * under us because it is not marked as T_FINISHED yet */
 	if (journal->j_commit_callback)
 		journal->j_commit_callback(journal, commit_transaction);
 
 	trace_jbd2_end_commit(journal, commit_transaction);
 	jbd_debug(1, "JBD2: commit %d complete, head %d\n",
 		  journal->j_commit_sequence, journal->j_tail_sequence);
-	if (to_free)
-		jbd2_journal_free_transaction(commit_transaction);
 
+	write_lock(&journal->j_state_lock);
+	spin_lock(&journal->j_list_lock);
+	commit_transaction->t_state = T_FINISHED;
+	/* Recheck checkpoint lists after j_list_lock was dropped */
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
+		__jbd2_journal_drop_transaction(journal, commit_transaction);
+		jbd2_journal_free_transaction(commit_transaction);
+	}
+	spin_unlock(&journal->j_list_lock);
+	write_unlock(&journal->j_state_lock);
 	wake_up(&journal->j_wait_done_commit);
 }
diff -druNp linux-libre-3.8-gnu1/fs/jbd2/journal.c linux-libre-3.8.13-gnu1/fs/jbd2/journal.c
--- linux-libre-3.8-gnu1/fs/jbd2/journal.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/jbd2/journal.c	2013-05-11 16:57:46.000000000 -0400
@@ -698,6 +698,37 @@ int jbd2_log_wait_commit(journal_t *jour
 }
 
 /*
+ * When this function returns the transaction corresponding to tid
+ * will be completed.  If the transaction has currently running, start
+ * committing that transaction before waiting for it to complete.  If
+ * the transaction id is stale, it is by definition already completed,
+ * so just return SUCCESS.
+ */
+int jbd2_complete_transaction(journal_t *journal, tid_t tid)
+{
+	int	need_to_wait = 1;
+
+	read_lock(&journal->j_state_lock);
+	if (journal->j_running_transaction &&
+	    journal->j_running_transaction->t_tid == tid) {
+		if (journal->j_commit_request != tid) {
+			/* transaction not yet started, so request it */
+			read_unlock(&journal->j_state_lock);
+			jbd2_log_start_commit(journal, tid);
+			goto wait_commit;
+		}
+	} else if (!(journal->j_committing_transaction &&
+		     journal->j_committing_transaction->t_tid == tid))
+		need_to_wait = 0;
+	read_unlock(&journal->j_state_lock);
+	if (!need_to_wait)
+		return 0;
+wait_commit:
+	return jbd2_log_wait_commit(journal, tid);
+}
+EXPORT_SYMBOL(jbd2_complete_transaction);
+
+/*
  * Log buffer allocation routines:
  */
 
diff -druNp linux-libre-3.8-gnu1/fs/jbd2/transaction.c linux-libre-3.8.13-gnu1/fs/jbd2/transaction.c
--- linux-libre-3.8-gnu1/fs/jbd2/transaction.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/jbd2/transaction.c	2013-05-11 16:57:46.000000000 -0400
@@ -1047,9 +1047,12 @@ out:
 void jbd2_journal_set_triggers(struct buffer_head *bh,
 			       struct jbd2_buffer_trigger_type *type)
 {
-	struct journal_head *jh = bh2jh(bh);
+	struct journal_head *jh = jbd2_journal_grab_journal_head(bh);
 
+	if (WARN_ON(!jh))
+		return;
 	jh->b_triggers = type;
+	jbd2_journal_put_journal_head(jh);
 }
 
 void jbd2_buffer_frozen_trigger(struct journal_head *jh, void *mapped_data,
@@ -1101,17 +1104,18 @@ int jbd2_journal_dirty_metadata(handle_t
 {
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
-	struct journal_head *jh = bh2jh(bh);
+	struct journal_head *jh;
 	int ret = 0;
 
-	jbd_debug(5, "journal_head %p\n", jh);
-	JBUFFER_TRACE(jh, "entry");
 	if (is_handle_aborted(handle))
 		goto out;
-	if (!buffer_jbd(bh)) {
+	jh = jbd2_journal_grab_journal_head(bh);
+	if (!jh) {
 		ret = -EUCLEAN;
 		goto out;
 	}
+	jbd_debug(5, "journal_head %p\n", jh);
+	JBUFFER_TRACE(jh, "entry");
 
 	jbd_lock_bh_state(bh);
 
@@ -1202,6 +1206,7 @@ int jbd2_journal_dirty_metadata(handle_t
 	spin_unlock(&journal->j_list_lock);
 out_unlock_bh:
 	jbd_unlock_bh_state(bh);
+	jbd2_journal_put_journal_head(jh);
 out:
 	JBUFFER_TRACE(jh, "exit");
 	WARN_ON(ret);	/* All errors are bugs, so dump the stack */
diff -druNp linux-libre-3.8-gnu1/fs/lockd/clntlock.c linux-libre-3.8.13-gnu1/fs/lockd/clntlock.c
--- linux-libre-3.8-gnu1/fs/lockd/clntlock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/lockd/clntlock.c	2013-05-11 16:57:46.000000000 -0400
@@ -144,6 +144,9 @@ int nlmclnt_block(struct nlm_wait *block
 			timeout);
 	if (ret < 0)
 		return -ERESTARTSYS;
+	/* Reset the lock status after a server reboot so we resend */
+	if (block->b_status == nlm_lck_denied_grace_period)
+		block->b_status = nlm_lck_blocked;
 	req->a_res.status = block->b_status;
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/fs/namei.c linux-libre-3.8.13-gnu1/fs/namei.c
--- linux-libre-3.8-gnu1/fs/namei.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/namei.c	2013-05-11 16:57:46.000000000 -0400
@@ -693,8 +693,6 @@ void nd_jump_link(struct nameidata *nd,
 	nd->path = *path;
 	nd->inode = nd->path.dentry->d_inode;
 	nd->flags |= LOOKUP_JUMPED;
-
-	BUG_ON(nd->inode->i_op->follow_link);
 }
 
 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
diff -druNp linux-libre-3.8-gnu1/fs/namespace.c linux-libre-3.8.13-gnu1/fs/namespace.c
--- linux-libre-3.8-gnu1/fs/namespace.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/namespace.c	2013-05-11 16:57:46.000000000 -0400
@@ -798,6 +798,10 @@ static struct mount *clone_mnt(struct mo
 	}
 
 	mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
+	/* Don't allow unprivileged users to change mount flags */
+	if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
+		mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
+
 	atomic_inc(&sb->s_active);
 	mnt->mnt.mnt_sb = sb;
 	mnt->mnt.mnt_root = dget(root);
@@ -1238,6 +1242,14 @@ static int do_umount(struct mount *mnt,
 }
 
 /*
+ * Is the caller allowed to modify his namespace?
+ */
+static inline bool may_mount(void)
+{
+	return ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN);
+}
+
+/*
  * Now umount can handle mount points as well as block devices.
  * This is important for filesystems which use unnamed block devices.
  *
@@ -1255,6 +1267,9 @@ SYSCALL_DEFINE2(umount, char __user *, n
 	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
 		return -EINVAL;
 
+	if (!may_mount())
+		return -EPERM;
+
 	if (!(flags & UMOUNT_NOFOLLOW))
 		lookup_flags |= LOOKUP_FOLLOW;
 
@@ -1268,10 +1283,6 @@ SYSCALL_DEFINE2(umount, char __user *, n
 	if (!check_mnt(mnt))
 		goto dput_and_out;
 
-	retval = -EPERM;
-	if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
-		goto dput_and_out;
-
 	retval = do_umount(mnt, flags);
 dput_and_out:
 	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
@@ -1295,7 +1306,7 @@ SYSCALL_DEFINE1(oldumount, char __user *
 
 static int mount_is_safe(struct path *path)
 {
-	if (ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
+	if (may_mount())
 		return 0;
 	return -EPERM;
 #ifdef notyet
@@ -1633,7 +1644,7 @@ static int do_change_type(struct path *p
 	int type;
 	int err = 0;
 
-	if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
+	if (!may_mount())
 		return -EPERM;
 
 	if (path->dentry != path->mnt->mnt_root)
@@ -1729,6 +1740,9 @@ static int change_mount_flags(struct vfs
 	if (readonly_request == __mnt_is_readonly(mnt))
 		return 0;
 
+	if (mnt->mnt_flags & MNT_LOCK_READONLY)
+		return -EPERM;
+
 	if (readonly_request)
 		error = mnt_make_readonly(real_mount(mnt));
 	else
@@ -1797,7 +1811,7 @@ static int do_move_mount(struct path *pa
 	struct mount *p;
 	struct mount *old;
 	int err = 0;
-	if (!ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
+	if (!may_mount())
 		return -EPERM;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1933,16 +1947,14 @@ static int do_new_mount(struct path *pat
 			int mnt_flags, const char *name, void *data)
 {
 	struct file_system_type *type;
-	struct user_namespace *user_ns;
+	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
 	struct vfsmount *mnt;
 	int err;
 
 	if (!fstype)
 		return -EINVAL;
 
-	/* we need capabilities... */
-	user_ns = real_mount(path->mnt)->mnt_ns->user_ns;
-	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
+	if (!may_mount())
 		return -EPERM;
 
 	type = get_fs_type(fstype);
@@ -2360,7 +2372,7 @@ static struct mnt_namespace *dup_mnt_ns(
 	/* First pass: copy the tree topology */
 	copy_flags = CL_COPY_ALL | CL_EXPIRE;
 	if (user_ns != mnt_ns->user_ns)
-		copy_flags |= CL_SHARED_TO_SLAVE;
+		copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
 	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
 	if (IS_ERR(new)) {
 		up_write(&namespace_sem);
@@ -2567,7 +2579,7 @@ SYSCALL_DEFINE2(pivot_root, const char _
 	struct mount *new_mnt, *root_mnt;
 	int error;
 
-	if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
+	if (!may_mount())
 		return -EPERM;
 
 	error = user_path_dir(new_root, &new);
@@ -2753,6 +2765,51 @@ bool our_mnt(struct vfsmount *mnt)
 	return check_mnt(real_mount(mnt));
 }
 
+bool current_chrooted(void)
+{
+	/* Does the current process have a non-standard root */
+	struct path ns_root;
+	struct path fs_root;
+	bool chrooted;
+
+	/* Find the namespace root */
+	ns_root.mnt = &current->nsproxy->mnt_ns->root->mnt;
+	ns_root.dentry = ns_root.mnt->mnt_root;
+	path_get(&ns_root);
+	while (d_mountpoint(ns_root.dentry) && follow_down_one(&ns_root))
+		;
+
+	get_fs_root(current->fs, &fs_root);
+
+	chrooted = !path_equal(&fs_root, &ns_root);
+
+	path_put(&fs_root);
+	path_put(&ns_root);
+
+	return chrooted;
+}
+
+void update_mnt_policy(struct user_namespace *userns)
+{
+	struct mnt_namespace *ns = current->nsproxy->mnt_ns;
+	struct mount *mnt;
+
+	down_read(&namespace_sem);
+	list_for_each_entry(mnt, &ns->list, mnt_list) {
+		switch (mnt->mnt.mnt_sb->s_magic) {
+		case SYSFS_MAGIC:
+			userns->may_mount_sysfs = true;
+			break;
+		case PROC_SUPER_MAGIC:
+			userns->may_mount_proc = true;
+			break;
+		}
+		if (userns->may_mount_sysfs && userns->may_mount_proc)
+			break;
+	}
+	up_read(&namespace_sem);
+}
+
 static void *mntns_get(struct task_struct *task)
 {
 	struct mnt_namespace *ns = NULL;
diff -druNp linux-libre-3.8-gnu1/fs/nfs/blocklayout/blocklayout.c linux-libre-3.8.13-gnu1/fs/nfs/blocklayout/blocklayout.c
--- linux-libre-3.8-gnu1/fs/nfs/blocklayout/blocklayout.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/blocklayout/blocklayout.c	2013-05-11 16:57:46.000000000 -0400
@@ -1273,6 +1273,7 @@ static const struct nfs_pageio_ops bl_pg
 static struct pnfs_layoutdriver_type blocklayout_type = {
 	.id				= LAYOUT_BLOCK_VOLUME,
 	.name				= "LAYOUT_BLOCK_VOLUME",
+	.owner				= THIS_MODULE,
 	.read_pagelist			= bl_read_pagelist,
 	.write_pagelist			= bl_write_pagelist,
 	.alloc_layout_hdr		= bl_alloc_layout_hdr,
diff -druNp linux-libre-3.8-gnu1/fs/nfs/blocklayout/blocklayoutdm.c linux-libre-3.8.13-gnu1/fs/nfs/blocklayout/blocklayoutdm.c
--- linux-libre-3.8-gnu1/fs/nfs/blocklayout/blocklayoutdm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/blocklayout/blocklayoutdm.c	2013-05-11 16:57:46.000000000 -0400
@@ -55,7 +55,8 @@ static void dev_remove(struct net *net,
 
 	bl_pipe_msg.bl_wq = &nn->bl_wq;
 	memset(msg, 0, sizeof(*msg));
-	msg->data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS);
+	msg->len = sizeof(bl_msg) + bl_msg.totallen;
+	msg->data = kzalloc(msg->len, GFP_NOFS);
 	if (!msg->data)
 		goto out;
 
@@ -66,7 +67,6 @@ static void dev_remove(struct net *net,
 	memcpy(msg->data, &bl_msg, sizeof(bl_msg));
 	dataptr = (uint8_t *) msg->data;
 	memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
-	msg->len = sizeof(bl_msg) + bl_msg.totallen;
 
 	add_wait_queue(&nn->bl_wq, &wq);
 	if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) {
diff -druNp linux-libre-3.8-gnu1/fs/nfs/callback_proc.c linux-libre-3.8.13-gnu1/fs/nfs/callback_proc.c
--- linux-libre-3.8-gnu1/fs/nfs/callback_proc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/callback_proc.c	2013-05-11 16:57:46.000000000 -0400
@@ -183,60 +183,15 @@ static u32 initiate_file_draining(struct
 static u32 initiate_bulk_draining(struct nfs_client *clp,
 				  struct cb_layoutrecallargs *args)
 {
-	struct nfs_server *server;
-	struct pnfs_layout_hdr *lo;
-	struct inode *ino;
-	u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
-	struct pnfs_layout_hdr *tmp;
-	LIST_HEAD(recall_list);
-	LIST_HEAD(free_me_list);
-	struct pnfs_layout_range range = {
-		.iomode = IOMODE_ANY,
-		.offset = 0,
-		.length = NFS4_MAX_UINT64,
-	};
-
-	spin_lock(&clp->cl_lock);
-	rcu_read_lock();
-	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-		if ((args->cbl_recall_type == RETURN_FSID) &&
-		    memcmp(&server->fsid, &args->cbl_fsid,
-			   sizeof(struct nfs_fsid)))
-			continue;
-
-		list_for_each_entry(lo, &server->layouts, plh_layouts) {
-			ino = igrab(lo->plh_inode);
-			if (!ino)
-				continue;
-			spin_lock(&ino->i_lock);
-			/* Is this layout in the process of being freed? */
-			if (NFS_I(ino)->layout != lo) {
-				spin_unlock(&ino->i_lock);
-				iput(ino);
-				continue;
-			}
-			pnfs_get_layout_hdr(lo);
-			spin_unlock(&ino->i_lock);
-			list_add(&lo->plh_bulk_recall, &recall_list);
-		}
-	}
-	rcu_read_unlock();
-	spin_unlock(&clp->cl_lock);
+	int stat;
 
-	list_for_each_entry_safe(lo, tmp,
-				 &recall_list, plh_bulk_recall) {
-		ino = lo->plh_inode;
-		spin_lock(&ino->i_lock);
-		set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
-		if (pnfs_mark_matching_lsegs_invalid(lo, &free_me_list, &range))
-			rv = NFS4ERR_DELAY;
-		list_del_init(&lo->plh_bulk_recall);
-		spin_unlock(&ino->i_lock);
-		pnfs_free_lseg_list(&free_me_list);
-		pnfs_put_layout_hdr(lo);
-		iput(ino);
-	}
-	return rv;
+	if (args->cbl_recall_type == RETURN_FSID)
+		stat = pnfs_destroy_layouts_byfsid(clp, &args->cbl_fsid, true);
+	else
+		stat = pnfs_destroy_layouts_byclid(clp, true);
+	if (stat != 0)
+		return NFS4ERR_DELAY;
+	return NFS4ERR_NOMATCHING_LAYOUT;
 }
 
 static u32 do_callback_layoutrecall(struct nfs_client *clp,
diff -druNp linux-libre-3.8-gnu1/fs/nfs/idmap.c linux-libre-3.8.13-gnu1/fs/nfs/idmap.c
--- linux-libre-3.8-gnu1/fs/nfs/idmap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/idmap.c	2013-05-11 16:57:46.000000000 -0400
@@ -725,9 +725,9 @@ out1:
 	return ret;
 }
 
-static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data)
+static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
 {
-	return key_instantiate_and_link(key, data, strlen(data) + 1,
+	return key_instantiate_and_link(key, data, datalen,
 					id_resolver_cache->thread_keyring,
 					authkey);
 }
@@ -737,6 +737,7 @@ static int nfs_idmap_read_and_verify_mes
 		struct key *key, struct key *authkey)
 {
 	char id_str[NFS_UINT_MAXLEN];
+	size_t len;
 	int ret = -ENOKEY;
 
 	/* ret = -ENOKEY */
@@ -746,13 +747,15 @@ static int nfs_idmap_read_and_verify_mes
 	case IDMAP_CONV_NAMETOID:
 		if (strcmp(upcall->im_name, im->im_name) != 0)
 			break;
-		sprintf(id_str, "%d", im->im_id);
-		ret = nfs_idmap_instantiate(key, authkey, id_str);
+		/* Note: here we store the NUL terminator too */
+		len = sprintf(id_str, "%d", im->im_id) + 1;
+		ret = nfs_idmap_instantiate(key, authkey, id_str, len);
 		break;
 	case IDMAP_CONV_IDTONAME:
 		if (upcall->im_id != im->im_id)
 			break;
-		ret = nfs_idmap_instantiate(key, authkey, im->im_name);
+		len = strlen(im->im_name);
+		ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
 		break;
 	default:
 		ret = -EINVAL;
diff -druNp linux-libre-3.8-gnu1/fs/nfs/nfs4client.c linux-libre-3.8.13-gnu1/fs/nfs/nfs4client.c
--- linux-libre-3.8-gnu1/fs/nfs/nfs4client.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/nfs4client.c	2013-05-11 16:57:46.000000000 -0400
@@ -300,7 +300,7 @@ int nfs40_walk_client_list(struct nfs_cl
 			   struct rpc_cred *cred)
 {
 	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
-	struct nfs_client *pos, *n, *prev = NULL;
+	struct nfs_client *pos, *prev = NULL;
 	struct nfs4_setclientid_res clid = {
 		.clientid	= new->cl_clientid,
 		.confirm	= new->cl_confirm,
@@ -308,10 +308,23 @@ int nfs40_walk_client_list(struct nfs_cl
 	int status = -NFS4ERR_STALE_CLIENTID;
 
 	spin_lock(&nn->nfs_client_lock);
-	list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 		/* If "pos" isn't marked ready, we can't trust the
 		 * remaining fields in "pos" */
-		if (pos->cl_cons_state < NFS_CS_READY)
+		if (pos->cl_cons_state > NFS_CS_READY) {
+			atomic_inc(&pos->cl_count);
+			spin_unlock(&nn->nfs_client_lock);
+
+			if (prev)
+				nfs_put_client(prev);
+			prev = pos;
+
+			status = nfs_wait_client_init_complete(pos);
+			spin_lock(&nn->nfs_client_lock);
+			if (status < 0)
+				continue;
+		}
+		if (pos->cl_cons_state != NFS_CS_READY)
 			continue;
 
 		if (pos->rpc_ops != new->rpc_ops)
@@ -423,16 +436,16 @@ int nfs41_walk_client_list(struct nfs_cl
 			   struct rpc_cred *cred)
 {
 	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
-	struct nfs_client *pos, *n, *prev = NULL;
+	struct nfs_client *pos, *prev = NULL;
 	int status = -NFS4ERR_STALE_CLIENTID;
 
 	spin_lock(&nn->nfs_client_lock);
-	list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 		/* If "pos" isn't marked ready, we can't trust the
 		 * remaining fields in "pos", especially the client
 		 * ID and serverowner fields.  Wait for CREATE_SESSION
 		 * to finish. */
-		if (pos->cl_cons_state < NFS_CS_READY) {
+		if (pos->cl_cons_state > NFS_CS_READY) {
 			atomic_inc(&pos->cl_count);
 			spin_unlock(&nn->nfs_client_lock);
 
@@ -440,18 +453,17 @@ int nfs41_walk_client_list(struct nfs_cl
 				nfs_put_client(prev);
 			prev = pos;
 
-			nfs4_schedule_lease_recovery(pos);
 			status = nfs_wait_client_init_complete(pos);
-			if (status < 0) {
-				nfs_put_client(pos);
-				spin_lock(&nn->nfs_client_lock);
-				continue;
+			if (status == 0) {
+				nfs4_schedule_lease_recovery(pos);
+				status = nfs4_wait_clnt_recover(pos);
 			}
-			status = pos->cl_cons_state;
 			spin_lock(&nn->nfs_client_lock);
 			if (status < 0)
 				continue;
 		}
+		if (pos->cl_cons_state != NFS_CS_READY)
+			continue;
 
 		if (pos->rpc_ops != new->rpc_ops)
 			continue;
@@ -469,17 +481,18 @@ int nfs41_walk_client_list(struct nfs_cl
 			continue;
 
 		atomic_inc(&pos->cl_count);
-		spin_unlock(&nn->nfs_client_lock);
+		*result = pos;
+		status = 0;
 		dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
 			__func__, pos, atomic_read(&pos->cl_count));
-
-		*result = pos;
-		return 0;
+		break;
 	}
 
 	/* No matching nfs_client found. */
 	spin_unlock(&nn->nfs_client_lock);
 	dprintk("NFS: <-- %s status = %d\n", __func__, status);
+	if (prev)
+		nfs_put_client(prev);
 	return status;
 }
 #endif	/* CONFIG_NFS_V4_1 */
diff -druNp linux-libre-3.8-gnu1/fs/nfs/nfs4filelayout.c linux-libre-3.8.13-gnu1/fs/nfs/nfs4filelayout.c
--- linux-libre-3.8-gnu1/fs/nfs/nfs4filelayout.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/nfs4filelayout.c	2013-05-11 16:57:46.000000000 -0400
@@ -99,7 +99,8 @@ static void filelayout_reset_write(struc
 
 		task->tk_status = pnfs_write_done_resend_to_mds(hdr->inode,
 							&hdr->pages,
-							hdr->completion_ops);
+							hdr->completion_ops,
+							hdr->dreq);
 	}
 }
 
@@ -119,7 +120,8 @@ static void filelayout_reset_read(struct
 
 		task->tk_status = pnfs_read_done_resend_to_mds(hdr->inode,
 							&hdr->pages,
-							hdr->completion_ops);
+							hdr->completion_ops,
+							hdr->dreq);
 	}
 }
 
@@ -127,7 +129,6 @@ static void filelayout_fenceme(struct in
 {
 	if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
 		return;
-	clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
 	pnfs_return_layout(inode);
 }
 
diff -druNp linux-libre-3.8-gnu1/fs/nfs/nfs4proc.c linux-libre-3.8.13-gnu1/fs/nfs/nfs4proc.c
--- linux-libre-3.8-gnu1/fs/nfs/nfs4proc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/nfs4proc.c	2013-05-11 16:57:46.000000000 -0400
@@ -1374,6 +1374,12 @@ int nfs4_open_delegation_recall(struct n
 			case -ENOMEM:
 				err = 0;
 				goto out;
+			case -NFS4ERR_DELAY:
+			case -NFS4ERR_GRACE:
+				set_bit(NFS_DELEGATED_STATE, &state->flags);
+				ssleep(1);
+				err = -EAGAIN;
+				goto out;
 		}
 		err = nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -1463,7 +1469,7 @@ static void nfs4_open_prepare(struct rpc
 	struct nfs4_state_owner *sp = data->owner;
 
 	if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
-		return;
+		goto out_wait;
 	/*
 	 * Check if we still need to send an OPEN call, or if we can use
 	 * a delegation instead.
@@ -1498,6 +1504,7 @@ unlock_no_action:
 	rcu_read_unlock();
 out_no_action:
 	task->tk_action = NULL;
+out_wait:
 	nfs4_sequence_done(task, &data->o_res.seq_res);
 }
 
@@ -2150,7 +2157,7 @@ static void nfs4_close_prepare(struct rp
 
 	dprintk("%s: begin!\n", __func__);
 	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
-		return;
+		goto out_wait;
 
 	task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
 	calldata->arg.fmode = FMODE_READ|FMODE_WRITE;
@@ -2172,16 +2179,14 @@ static void nfs4_close_prepare(struct rp
 
 	if (!call_close) {
 		/* Note: exit _without_ calling nfs4_close_done */
-		task->tk_action = NULL;
-		nfs4_sequence_done(task, &calldata->res.seq_res);
-		goto out;
+		goto out_no_action;
 	}
 
 	if (calldata->arg.fmode == 0) {
 		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
 		if (calldata->roc &&
 		    pnfs_roc_drain(inode, &calldata->roc_barrier, task))
-			goto out;
+			goto out_wait;
 	}
 
 	nfs_fattr_init(calldata->res.fattr);
@@ -2191,8 +2196,12 @@ static void nfs4_close_prepare(struct rp
 				&calldata->res.seq_res,
 				task) != 0)
 		nfs_release_seqid(calldata->arg.seqid);
-out:
 	dprintk("%s: done!\n", __func__);
+	return;
+out_no_action:
+	task->tk_action = NULL;
+out_wait:
+	nfs4_sequence_done(task, &calldata->res.seq_res);
 }
 
 static const struct rpc_call_ops nfs4_close_ops = {
@@ -4423,12 +4432,10 @@ static void nfs4_locku_prepare(struct rp
 	struct nfs4_unlockdata *calldata = data;
 
 	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
-		return;
+		goto out_wait;
 	if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
 		/* Note: exit _without_ running nfs4_locku_done */
-		task->tk_action = NULL;
-		nfs4_sequence_done(task, &calldata->res.seq_res);
-		return;
+		goto out_no_action;
 	}
 	calldata->timestamp = jiffies;
 	if (nfs4_setup_sequence(calldata->server,
@@ -4436,6 +4443,11 @@ static void nfs4_locku_prepare(struct rp
 				&calldata->res.seq_res,
 				task) != 0)
 		nfs_release_seqid(calldata->arg.seqid);
+	return;
+out_no_action:
+	task->tk_action = NULL;
+out_wait:
+	nfs4_sequence_done(task, &calldata->res.seq_res);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4501,9 +4513,9 @@ static int nfs4_proc_unlck(struct nfs4_s
 	if (status != 0)
 		goto out;
 	/* Is this a delegated lock? */
-	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
-		goto out;
 	lsp = request->fl_u.nfs4_fl.owner;
+	if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0)
+		goto out;
 	seqid = nfs_alloc_seqid(&lsp->ls_seqid, GFP_KERNEL);
 	status = -ENOMEM;
 	if (seqid == NULL)
@@ -4576,7 +4588,7 @@ static void nfs4_lock_prepare(struct rpc
 
 	dprintk("%s: begin!\n", __func__);
 	if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
-		return;
+		goto out_wait;
 	/* Do we need to do an open_to_lock_owner? */
 	if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
 		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
@@ -4596,6 +4608,8 @@ static void nfs4_lock_prepare(struct rpc
 	nfs_release_seqid(data->arg.open_seqid);
 out_release_lock_seqid:
 	nfs_release_seqid(data->arg.lock_seqid);
+out_wait:
+	nfs4_sequence_done(task, &data->res.seq_res);
 	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
 }
 
@@ -6079,11 +6093,13 @@ static struct page **nfs4_alloc_pages(si
 static void nfs4_layoutget_release(void *calldata)
 {
 	struct nfs4_layoutget *lgp = calldata;
-	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+	struct inode *inode = lgp->args.inode;
+	struct nfs_server *server = NFS_SERVER(inode);
 	size_t max_pages = max_response_pages(server);
 
 	dprintk("--> %s\n", __func__);
 	nfs4_free_pages(lgp->args.layout.pages, max_pages);
+	pnfs_put_layout_hdr(NFS_I(inode)->layout);
 	put_nfs_open_context(lgp->args.ctx);
 	kfree(calldata);
 	dprintk("<-- %s\n", __func__);
@@ -6098,7 +6114,8 @@ static const struct rpc_call_ops nfs4_la
 struct pnfs_layout_segment *
 nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
 {
-	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+	struct inode *inode = lgp->args.inode;
+	struct nfs_server *server = NFS_SERVER(inode);
 	size_t max_pages = max_response_pages(server);
 	struct rpc_task *task;
 	struct rpc_message msg = {
@@ -6128,13 +6145,18 @@ nfs4_proc_layoutget(struct nfs4_layoutge
 	lgp->res.layoutp = &lgp->args.layout;
 	lgp->res.seq_res.sr_slot = NULL;
 	nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
+
+	/* nfs4_layoutget_release calls pnfs_put_layout_hdr */
+	pnfs_get_layout_hdr(NFS_I(inode)->layout);
+
 	task = rpc_run_task(&task_setup_data);
 	if (IS_ERR(task))
 		return ERR_CAST(task);
 	status = nfs4_wait_for_completion_rpc_task(task);
 	if (status == 0)
 		status = task->tk_status;
-	if (status == 0)
+	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
+	if (status == 0 && lgp->res.layoutp->len)
 		lseg = pnfs_layout_process(lgp);
 	rpc_put_task(task);
 	dprintk("<-- %s status=%d\n", __func__, status);
@@ -6350,22 +6372,8 @@ nfs4_layoutcommit_done(struct rpc_task *
 static void nfs4_layoutcommit_release(void *calldata)
 {
 	struct nfs4_layoutcommit_data *data = calldata;
-	struct pnfs_layout_segment *lseg, *tmp;
-	unsigned long *bitlock = &NFS_I(data->args.inode)->flags;
 
 	pnfs_cleanup_layoutcommit(data);
-	/* Matched by references in pnfs_set_layoutcommit */
-	list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
-		list_del_init(&lseg->pls_lc_list);
-		if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
-				       &lseg->pls_flags))
-			pnfs_put_lseg(lseg);
-	}
-
-	clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
-	smp_mb__after_clear_bit();
-	wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
-
 	put_rpccred(data->cred);
 	kfree(data);
 }
diff -druNp linux-libre-3.8-gnu1/fs/nfs/nfs4state.c linux-libre-3.8.13-gnu1/fs/nfs/nfs4state.c
--- linux-libre-3.8-gnu1/fs/nfs/nfs4state.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/nfs4state.c	2013-05-11 16:57:46.000000000 -0400
@@ -1877,7 +1877,13 @@ again:
 			status = PTR_ERR(clnt);
 			break;
 		}
-		clp->cl_rpcclient = clnt;
+		/* Note: this is safe because we haven't yet marked the
+		 * client as ready, so we are the only user of
+		 * clp->cl_rpcclient
+		 */
+		clnt = xchg(&clp->cl_rpcclient, clnt);
+		rpc_shutdown_client(clnt);
+		clnt = clp->cl_rpcclient;
 		goto again;
 
 	case -NFS4ERR_MINOR_VERS_MISMATCH:
diff -druNp linux-libre-3.8-gnu1/fs/nfs/objlayout/objio_osd.c linux-libre-3.8.13-gnu1/fs/nfs/objlayout/objio_osd.c
--- linux-libre-3.8-gnu1/fs/nfs/objlayout/objio_osd.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/objlayout/objio_osd.c	2013-05-11 16:57:46.000000000 -0400
@@ -647,6 +647,7 @@ static struct pnfs_layoutdriver_type obj
 	.flags                   = PNFS_LAYOUTRET_ON_SETATTR |
 				   PNFS_LAYOUTRET_ON_ERROR,
 
+	.owner		       	 = THIS_MODULE,
 	.alloc_layout_hdr        = objlayout_alloc_layout_hdr,
 	.free_layout_hdr         = objlayout_free_layout_hdr,
 
diff -druNp linux-libre-3.8-gnu1/fs/nfs/pnfs.c linux-libre-3.8.13-gnu1/fs/nfs/pnfs.c
--- linux-libre-3.8-gnu1/fs/nfs/pnfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/pnfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -417,6 +417,16 @@ should_free_lseg(struct pnfs_layout_rang
 	       lo_seg_intersecting(lseg_range, recall_range);
 }
 
+static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
+		struct list_head *tmp_list)
+{
+	if (!atomic_dec_and_test(&lseg->pls_refcount))
+		return false;
+	pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
+	list_add(&lseg->pls_list, tmp_list);
+	return true;
+}
+
 /* Returns 1 if lseg is removed from list, 0 otherwise */
 static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
 			     struct list_head *tmp_list)
@@ -430,11 +440,8 @@ static int mark_lseg_invalid(struct pnfs
 		 */
 		dprintk("%s: lseg %p ref %d\n", __func__, lseg,
 			atomic_read(&lseg->pls_refcount));
-		if (atomic_dec_and_test(&lseg->pls_refcount)) {
-			pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
-			list_add(&lseg->pls_list, tmp_list);
+		if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list))
 			rv = 1;
-		}
 	}
 	return rv;
 }
@@ -505,37 +512,147 @@ pnfs_destroy_layout(struct nfs_inode *nf
 }
 EXPORT_SYMBOL_GPL(pnfs_destroy_layout);
 
-/*
- * Called by the state manger to remove all layouts established under an
- * expired lease.
- */
-void
-pnfs_destroy_all_layouts(struct nfs_client *clp)
+static bool
+pnfs_layout_add_bulk_destroy_list(struct inode *inode,
+		struct list_head *layout_list)
 {
-	struct nfs_server *server;
 	struct pnfs_layout_hdr *lo;
-	LIST_HEAD(tmp_list);
+	bool ret = false;
 
-	nfs4_deviceid_mark_client_invalid(clp);
-	nfs4_deviceid_purge_client(clp);
+	spin_lock(&inode->i_lock);
+	lo = NFS_I(inode)->layout;
+	if (lo != NULL && list_empty(&lo->plh_bulk_destroy)) {
+		pnfs_get_layout_hdr(lo);
+		list_add(&lo->plh_bulk_destroy, layout_list);
+		ret = true;
+	}
+	spin_unlock(&inode->i_lock);
+	return ret;
+}
+
+/* Caller must hold rcu_read_lock and clp->cl_lock */
+static int
+pnfs_layout_bulk_destroy_byserver_locked(struct nfs_client *clp,
+		struct nfs_server *server,
+		struct list_head *layout_list)
+{
+	struct pnfs_layout_hdr *lo, *next;
+	struct inode *inode;
+
+	list_for_each_entry_safe(lo, next, &server->layouts, plh_layouts) {
+		inode = igrab(lo->plh_inode);
+		if (inode == NULL)
+			continue;
+		list_del_init(&lo->plh_layouts);
+		if (pnfs_layout_add_bulk_destroy_list(inode, layout_list))
+			continue;
+		rcu_read_unlock();
+		spin_unlock(&clp->cl_lock);
+		iput(inode);
+		spin_lock(&clp->cl_lock);
+		rcu_read_lock();
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static int
+pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
+		bool is_bulk_recall)
+{
+	struct pnfs_layout_hdr *lo;
+	struct inode *inode;
+	struct pnfs_layout_range range = {
+		.iomode = IOMODE_ANY,
+		.offset = 0,
+		.length = NFS4_MAX_UINT64,
+	};
+	LIST_HEAD(lseg_list);
+	int ret = 0;
+
+	while (!list_empty(layout_list)) {
+		lo = list_entry(layout_list->next, struct pnfs_layout_hdr,
+				plh_bulk_destroy);
+		dprintk("%s freeing layout for inode %lu\n", __func__,
+			lo->plh_inode->i_ino);
+		inode = lo->plh_inode;
+		spin_lock(&inode->i_lock);
+		list_del_init(&lo->plh_bulk_destroy);
+		lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */
+		if (is_bulk_recall)
+			set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
+		if (pnfs_mark_matching_lsegs_invalid(lo, &lseg_list, &range))
+			ret = -EAGAIN;
+		spin_unlock(&inode->i_lock);
+		pnfs_free_lseg_list(&lseg_list);
+		pnfs_put_layout_hdr(lo);
+		iput(inode);
+	}
+	return ret;
+}
+
+int
+pnfs_destroy_layouts_byfsid(struct nfs_client *clp,
+		struct nfs_fsid *fsid,
+		bool is_recall)
+{
+	struct nfs_server *server;
+	LIST_HEAD(layout_list);
 
 	spin_lock(&clp->cl_lock);
 	rcu_read_lock();
+restart:
 	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-		if (!list_empty(&server->layouts))
-			list_splice_init(&server->layouts, &tmp_list);
+		if (memcmp(&server->fsid, fsid, sizeof(*fsid)) != 0)
+			continue;
+		if (pnfs_layout_bulk_destroy_byserver_locked(clp,
+				server,
+				&layout_list) != 0)
+			goto restart;
 	}
 	rcu_read_unlock();
 	spin_unlock(&clp->cl_lock);
 
-	while (!list_empty(&tmp_list)) {
-		lo = list_entry(tmp_list.next, struct pnfs_layout_hdr,
-				plh_layouts);
-		dprintk("%s freeing layout for inode %lu\n", __func__,
-			lo->plh_inode->i_ino);
-		list_del_init(&lo->plh_layouts);
-		pnfs_destroy_layout(NFS_I(lo->plh_inode));
+	if (list_empty(&layout_list))
+		return 0;
+	return pnfs_layout_free_bulk_destroy_list(&layout_list, is_recall);
+}
+
+int
+pnfs_destroy_layouts_byclid(struct nfs_client *clp,
+		bool is_recall)
+{
+	struct nfs_server *server;
+	LIST_HEAD(layout_list);
+
+	spin_lock(&clp->cl_lock);
+	rcu_read_lock();
+restart:
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		if (pnfs_layout_bulk_destroy_byserver_locked(clp,
+					server,
+					&layout_list) != 0)
+			goto restart;
 	}
+	rcu_read_unlock();
+	spin_unlock(&clp->cl_lock);
+
+	if (list_empty(&layout_list))
+		return 0;
+	return pnfs_layout_free_bulk_destroy_list(&layout_list, is_recall);
+}
+
+/*
+ * Called by the state manger to remove all layouts established under an
+ * expired lease.
+ */
+void
+pnfs_destroy_all_layouts(struct nfs_client *clp)
+{
+	nfs4_deviceid_mark_client_invalid(clp);
+	nfs4_deviceid_purge_client(clp);
+
+	pnfs_destroy_layouts_byclid(clp, false);
 }
 
 /*
@@ -667,6 +784,21 @@ send_layoutget(struct pnfs_layout_hdr *l
 	return lseg;
 }
 
+static void pnfs_clear_layoutcommit(struct inode *inode,
+		struct list_head *head)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct pnfs_layout_segment *lseg, *tmp;
+
+	if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
+		return;
+	list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) {
+		if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+			continue;
+		pnfs_lseg_dec_and_remove_zero(lseg, head);
+	}
+}
+
 /*
  * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
  * when the layout segment list is empty.
@@ -698,6 +830,7 @@ _pnfs_return_layout(struct inode *ino)
 	/* Reference matched in nfs4_layoutreturn_release */
 	pnfs_get_layout_hdr(lo);
 	empty = list_empty(&lo->plh_segs);
+	pnfs_clear_layoutcommit(ino, &tmp_list);
 	pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
 	/* Don't send a LAYOUTRETURN if list was initially empty */
 	if (empty) {
@@ -710,8 +843,6 @@ _pnfs_return_layout(struct inode *ino)
 	spin_unlock(&ino->i_lock);
 	pnfs_free_lseg_list(&tmp_list);
 
-	WARN_ON(test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags));
-
 	lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
 	if (unlikely(lrp == NULL)) {
 		status = -ENOMEM;
@@ -888,7 +1019,7 @@ alloc_init_layout_hdr(struct inode *ino,
 	atomic_set(&lo->plh_refcount, 1);
 	INIT_LIST_HEAD(&lo->plh_layouts);
 	INIT_LIST_HEAD(&lo->plh_segs);
-	INIT_LIST_HEAD(&lo->plh_bulk_recall);
+	INIT_LIST_HEAD(&lo->plh_bulk_destroy);
 	lo->plh_inode = ino;
 	lo->plh_lc_cred = get_rpccred(ctx->state->owner->so_cred);
 	return lo;
@@ -1312,13 +1443,15 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_test);
 
 int pnfs_write_done_resend_to_mds(struct inode *inode,
 				struct list_head *head,
-				const struct nfs_pgio_completion_ops *compl_ops)
+				const struct nfs_pgio_completion_ops *compl_ops,
+				struct nfs_direct_req *dreq)
 {
 	struct nfs_pageio_descriptor pgio;
 	LIST_HEAD(failed);
 
 	/* Resend all requests through the MDS */
 	nfs_pageio_init_write(&pgio, inode, FLUSH_STABLE, compl_ops);
+	pgio.pg_dreq = dreq;
 	while (!list_empty(head)) {
 		struct nfs_page *req = nfs_list_entry(head->next);
 
@@ -1347,13 +1480,13 @@ static void pnfs_ld_handle_write_error(s
 	dprintk("pnfs write error = %d\n", hdr->pnfs_error);
 	if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
 	    PNFS_LAYOUTRET_ON_ERROR) {
-		clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
 		pnfs_return_layout(hdr->inode);
 	}
 	if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
 		data->task.tk_status = pnfs_write_done_resend_to_mds(hdr->inode,
 							&hdr->pages,
-							hdr->completion_ops);
+							hdr->completion_ops,
+							hdr->dreq);
 }
 
 /*
@@ -1468,13 +1601,15 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_writep
 
 int pnfs_read_done_resend_to_mds(struct inode *inode,
 				struct list_head *head,
-				const struct nfs_pgio_completion_ops *compl_ops)
+				const struct nfs_pgio_completion_ops *compl_ops,
+				struct nfs_direct_req *dreq)
 {
 	struct nfs_pageio_descriptor pgio;
 	LIST_HEAD(failed);
 
 	/* Resend all requests through the MDS */
 	nfs_pageio_init_read(&pgio, inode, compl_ops);
+	pgio.pg_dreq = dreq;
 	while (!list_empty(head)) {
 		struct nfs_page *req = nfs_list_entry(head->next);
 
@@ -1499,13 +1634,13 @@ static void pnfs_ld_handle_read_error(st
 	dprintk("pnfs read error = %d\n", hdr->pnfs_error);
 	if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
 	    PNFS_LAYOUTRET_ON_ERROR) {
-		clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
 		pnfs_return_layout(hdr->inode);
 	}
 	if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
 		data->task.tk_status = pnfs_read_done_resend_to_mds(hdr->inode,
 							&hdr->pages,
-							hdr->completion_ops);
+							hdr->completion_ops,
+							hdr->dreq);
 }
 
 /*
@@ -1631,11 +1766,27 @@ static void pnfs_list_write_lseg(struct
 
 	list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
 		if (lseg->pls_range.iomode == IOMODE_RW &&
-		    test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+		    test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
 			list_add(&lseg->pls_lc_list, listp);
 	}
 }
 
+static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
+{
+	struct pnfs_layout_segment *lseg, *tmp;
+	unsigned long *bitlock = &NFS_I(inode)->flags;
+
+	/* Matched by references in pnfs_set_layoutcommit */
+	list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
+		list_del_init(&lseg->pls_lc_list);
+		pnfs_put_lseg(lseg);
+	}
+
+	clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
+	smp_mb__after_clear_bit();
+	wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+}
+
 void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
 {
 	pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode);
@@ -1680,6 +1831,7 @@ void pnfs_cleanup_layoutcommit(struct nf
 
 	if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
 		nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
+	pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list);
 }
 
 /*
diff -druNp linux-libre-3.8-gnu1/fs/nfs/pnfs.h linux-libre-3.8.13-gnu1/fs/nfs/pnfs.h
--- linux-libre-3.8-gnu1/fs/nfs/pnfs.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/pnfs.h	2013-05-11 16:57:46.000000000 -0400
@@ -132,7 +132,7 @@ struct pnfs_layoutdriver_type {
 struct pnfs_layout_hdr {
 	atomic_t		plh_refcount;
 	struct list_head	plh_layouts;   /* other client layouts */
-	struct list_head	plh_bulk_recall; /* clnt list of bulk recalls */
+	struct list_head	plh_bulk_destroy;
 	struct list_head	plh_segs;      /* layout segments list */
 	nfs4_stateid		plh_stateid;
 	atomic_t		plh_outstanding; /* number of RPCs out */
@@ -196,6 +196,11 @@ struct pnfs_layout_segment *pnfs_layout_
 void pnfs_free_lseg_list(struct list_head *tmp_list);
 void pnfs_destroy_layout(struct nfs_inode *);
 void pnfs_destroy_all_layouts(struct nfs_client *);
+int pnfs_destroy_layouts_byfsid(struct nfs_client *clp,
+		struct nfs_fsid *fsid,
+		bool is_recall);
+int pnfs_destroy_layouts_byclid(struct nfs_client *clp,
+		bool is_recall);
 void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo);
 void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
 			     const nfs4_stateid *new,
@@ -225,9 +230,11 @@ struct pnfs_layout_segment *pnfs_update_
 
 void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp);
 int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head,
-			const struct nfs_pgio_completion_ops *compl_ops);
+			const struct nfs_pgio_completion_ops *compl_ops,
+			struct nfs_direct_req *dreq);
 int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head,
-			const struct nfs_pgio_completion_ops *compl_ops);
+			const struct nfs_pgio_completion_ops *compl_ops,
+			struct nfs_direct_req *dreq);
 struct nfs4_threshold *pnfs_mdsthreshold_alloc(void);
 
 /* nfs4_deviceid_flags */
diff -druNp linux-libre-3.8-gnu1/fs/nfs/unlink.c linux-libre-3.8.13-gnu1/fs/nfs/unlink.c
--- linux-libre-3.8-gnu1/fs/nfs/unlink.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfs/unlink.c	2013-05-11 16:57:46.000000000 -0400
@@ -336,20 +336,14 @@ static void nfs_async_rename_done(struct
 	struct inode *old_dir = data->old_dir;
 	struct inode *new_dir = data->new_dir;
 	struct dentry *old_dentry = data->old_dentry;
-	struct dentry *new_dentry = data->new_dentry;
 
 	if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
 		rpc_restart_call_prepare(task);
 		return;
 	}
 
-	if (task->tk_status != 0) {
+	if (task->tk_status != 0)
 		nfs_cancel_async_unlink(old_dentry);
-		return;
-	}
-
-	d_drop(old_dentry);
-	d_drop(new_dentry);
 }
 
 /**
@@ -550,6 +544,18 @@ nfs_sillyrename(struct inode *dir, struc
 	error = rpc_wait_for_completion_task(task);
 	if (error == 0)
 		error = task->tk_status;
+	switch (error) {
+	case 0:
+		/* The rename succeeded */
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+		d_move(dentry, sdentry);
+		break;
+	case -ERESTARTSYS:
+		/* The result of the rename is unknown. Play it safe by
+		 * forcing a new lookup */
+		d_drop(dentry);
+		d_drop(sdentry);
+	}
 	rpc_put_task(task);
 out_dput:
 	dput(sdentry);
diff -druNp linux-libre-3.8-gnu1/fs/nfsd/nfs4proc.c linux-libre-3.8.13-gnu1/fs/nfsd/nfs4proc.c
--- linux-libre-3.8-gnu1/fs/nfsd/nfs4proc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfsd/nfs4proc.c	2013-05-11 16:57:46.000000000 -0400
@@ -931,14 +931,14 @@ nfsd4_write(struct svc_rqst *rqstp, stru
 	nfs4_lock_state();
 	status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
 					cstate, stateid, WR_STATE, &filp);
-	if (filp)
-		get_file(filp);
-	nfs4_unlock_state();
-
 	if (status) {
+		nfs4_unlock_state();
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		return status;
 	}
+	if (filp)
+		get_file(filp);
+	nfs4_unlock_state();
 
 	cnt = write->wr_buflen;
 	write->wr_how_written = write->wr_stable_how;
diff -druNp linux-libre-3.8-gnu1/fs/nfsd/nfs4state.c linux-libre-3.8.13-gnu1/fs/nfsd/nfs4state.c
--- linux-libre-3.8-gnu1/fs/nfsd/nfs4state.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfsd/nfs4state.c	2013-05-11 16:57:46.000000000 -0400
@@ -210,13 +210,7 @@ static void __nfs4_file_put_access(struc
 {
 	if (atomic_dec_and_test(&fp->fi_access[oflag])) {
 		nfs4_file_put_fd(fp, oflag);
-		/*
-		 * It's also safe to get rid of the RDWR open *if*
-		 * we no longer have need of the other kind of access
-		 * or if we already have the other kind of open:
-		 */
-		if (fp->fi_fds[1-oflag]
-			|| atomic_read(&fp->fi_access[1 - oflag]) == 0)
+		if (atomic_read(&fp->fi_access[1 - oflag]) == 0)
 			nfs4_file_put_fd(fp, O_RDWR);
 	}
 }
@@ -1060,6 +1054,8 @@ free_client(struct nfs4_client *clp)
 	}
 	free_svc_cred(&clp->cl_cred);
 	kfree(clp->cl_name.data);
+	idr_remove_all(&clp->cl_stateids);
+	idr_destroy(&clp->cl_stateids);
 	kfree(clp);
 }
 
diff -druNp linux-libre-3.8-gnu1/fs/nfsd/nfs4xdr.c linux-libre-3.8.13-gnu1/fs/nfsd/nfs4xdr.c
--- linux-libre-3.8-gnu1/fs/nfsd/nfs4xdr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfsd/nfs4xdr.c	2013-05-11 16:57:46.000000000 -0400
@@ -264,7 +264,7 @@ nfsd4_decode_fattr(struct nfsd4_compound
 		iattr->ia_valid |= ATTR_SIZE;
 	}
 	if (bmval[0] & FATTR4_WORD0_ACL) {
-		int nace;
+		u32 nace;
 		struct nfs4_ace *ace;
 
 		READ_BUF(4); len += 4;
@@ -344,10 +344,7 @@ nfsd4_decode_fattr(struct nfsd4_compound
 			   all 32 bits of 'nseconds'. */
 			READ_BUF(12);
 			len += 12;
-			READ32(dummy32);
-			if (dummy32)
-				return nfserr_inval;
-			READ32(iattr->ia_atime.tv_sec);
+			READ64(iattr->ia_atime.tv_sec);
 			READ32(iattr->ia_atime.tv_nsec);
 			if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
 				return nfserr_inval;
@@ -370,10 +367,7 @@ nfsd4_decode_fattr(struct nfsd4_compound
 			   all 32 bits of 'nseconds'. */
 			READ_BUF(12);
 			len += 12;
-			READ32(dummy32);
-			if (dummy32)
-				return nfserr_inval;
-			READ32(iattr->ia_mtime.tv_sec);
+			READ64(iattr->ia_mtime.tv_sec);
 			READ32(iattr->ia_mtime.tv_nsec);
 			if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
 				return nfserr_inval;
@@ -2386,8 +2380,7 @@ out_acl:
 	if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
 		if ((buflen -= 12) < 0)
 			goto out_resource;
-		WRITE32(0);
-		WRITE32(stat.atime.tv_sec);
+		WRITE64((s64)stat.atime.tv_sec);
 		WRITE32(stat.atime.tv_nsec);
 	}
 	if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
@@ -2400,15 +2393,13 @@ out_acl:
 	if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
 		if ((buflen -= 12) < 0)
 			goto out_resource;
-		WRITE32(0);
-		WRITE32(stat.ctime.tv_sec);
+		WRITE64((s64)stat.ctime.tv_sec);
 		WRITE32(stat.ctime.tv_nsec);
 	}
 	if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
 		if ((buflen -= 12) < 0)
 			goto out_resource;
-		WRITE32(0);
-		WRITE32(stat.mtime.tv_sec);
+		WRITE64((s64)stat.mtime.tv_sec);
 		WRITE32(stat.mtime.tv_nsec);
 	}
 	if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
diff -druNp linux-libre-3.8-gnu1/fs/nfsd/vfs.c linux-libre-3.8.13-gnu1/fs/nfsd/vfs.c
--- linux-libre-3.8-gnu1/fs/nfsd/vfs.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/nfsd/vfs.c	2013-05-11 16:57:46.000000000 -0400
@@ -1013,6 +1013,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
 	int			host_err;
 	int			stable = *stablep;
 	int			use_wgather;
+	loff_t			pos = offset;
 
 	dentry = file->f_path.dentry;
 	inode = dentry->d_inode;
@@ -1025,7 +1026,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
-	host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
+	host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &pos);
 	set_fs(oldfs);
 	if (host_err < 0)
 		goto out_nfserr;
diff -druNp linux-libre-3.8-gnu1/fs/notify/inotify/inotify_user.c linux-libre-3.8.13-gnu1/fs/notify/inotify/inotify_user.c
--- linux-libre-3.8-gnu1/fs/notify/inotify/inotify_user.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/notify/inotify/inotify_user.c	2013-05-11 16:57:46.000000000 -0400
@@ -574,10 +574,7 @@ static int inotify_update_existing_watch
 	int add = (arg & IN_MASK_ADD);
 	int ret;
 
-	/* don't allow invalid bits: we don't want flags set */
 	mask = inotify_arg_to_mask(arg);
-	if (unlikely(!(mask & IN_ALL_EVENTS)))
-		return -EINVAL;
 
 	fsn_mark = fsnotify_find_inode_mark(group, inode);
 	if (!fsn_mark)
@@ -627,10 +624,7 @@ static int inotify_new_watch(struct fsno
 	struct idr *idr = &group->inotify_data.idr;
 	spinlock_t *idr_lock = &group->inotify_data.idr_lock;
 
-	/* don't allow invalid bits: we don't want flags set */
 	mask = inotify_arg_to_mask(arg);
-	if (unlikely(!(mask & IN_ALL_EVENTS)))
-		return -EINVAL;
 
 	tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
 	if (unlikely(!tmp_i_mark))
@@ -757,6 +751,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int,
 	int ret;
 	unsigned flags = 0;
 
+	/* don't allow invalid bits: we don't want flags set */
+	if (unlikely(!(mask & ALL_INOTIFY_BITS)))
+		return -EINVAL;
+
 	f = fdget(fd);
 	if (unlikely(!f.file))
 		return -EBADF;
diff -druNp linux-libre-3.8-gnu1/fs/ocfs2/aops.c linux-libre-3.8.13-gnu1/fs/ocfs2/aops.c
--- linux-libre-3.8-gnu1/fs/ocfs2/aops.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ocfs2/aops.c	2013-05-11 16:57:46.000000000 -0400
@@ -593,9 +593,9 @@ static void ocfs2_dio_end_io(struct kioc
 	level = ocfs2_iocb_rw_locked_level(iocb);
 	ocfs2_rw_unlock(inode, level);
 
+	inode_dio_done(inode);
 	if (is_async)
 		aio_complete(iocb, ret, 0);
-	inode_dio_done(inode);
 }
 
 /*
diff -druNp linux-libre-3.8-gnu1/fs/ocfs2/dlmglue.c linux-libre-3.8.13-gnu1/fs/ocfs2/dlmglue.c
--- linux-libre-3.8-gnu1/fs/ocfs2/dlmglue.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ocfs2/dlmglue.c	2013-05-11 16:57:46.000000000 -0400
@@ -2545,6 +2545,7 @@ int ocfs2_super_lock(struct ocfs2_super
 	 * everything is up to the caller :) */
 	status = ocfs2_should_refresh_lock_res(lockres);
 	if (status < 0) {
+		ocfs2_cluster_unlock(osb, lockres, level);
 		mlog_errno(status);
 		goto bail;
 	}
@@ -2553,8 +2554,10 @@ int ocfs2_super_lock(struct ocfs2_super
 
 		ocfs2_complete_lock_res_refresh(lockres, status);
 
-		if (status < 0)
+		if (status < 0) {
+			ocfs2_cluster_unlock(osb, lockres, level);
 			mlog_errno(status);
+		}
 		ocfs2_track_lock_refresh(lockres);
 	}
 bail:
diff -druNp linux-libre-3.8-gnu1/fs/ocfs2/suballoc.c linux-libre-3.8.13-gnu1/fs/ocfs2/suballoc.c
--- linux-libre-3.8-gnu1/fs/ocfs2/suballoc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ocfs2/suballoc.c	2013-05-11 16:57:46.000000000 -0400
@@ -642,7 +642,7 @@ ocfs2_block_group_alloc_discontig(handle
 	 * cluster groups will be staying in cache for the duration of
 	 * this operation.
 	 */
-	ac->ac_allow_chain_relink = 0;
+	ac->ac_disable_chain_relink = 1;
 
 	/* Claim the first region */
 	status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits,
@@ -1823,7 +1823,7 @@ static int ocfs2_search_chain(struct ocf
 	 * Do this *after* figuring out how many bits we're taking out
 	 * of our target group.
 	 */
-	if (ac->ac_allow_chain_relink &&
+	if (!ac->ac_disable_chain_relink &&
 	    (prev_group_bh) &&
 	    (ocfs2_block_group_reasonably_empty(bg, res->sr_bits))) {
 		status = ocfs2_relink_block_group(handle, alloc_inode,
@@ -1928,7 +1928,6 @@ static int ocfs2_claim_suballoc_bits(str
 
 	victim = ocfs2_find_victim_chain(cl);
 	ac->ac_chain = victim;
-	ac->ac_allow_chain_relink = 1;
 
 	status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
 				    res, &bits_left);
@@ -1947,7 +1946,7 @@ static int ocfs2_claim_suballoc_bits(str
 	 * searching each chain in order. Don't allow chain relinking
 	 * because we only calculate enough journal credits for one
 	 * relink per alloc. */
-	ac->ac_allow_chain_relink = 0;
+	ac->ac_disable_chain_relink = 1;
 	for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i ++) {
 		if (i == victim)
 			continue;
diff -druNp linux-libre-3.8-gnu1/fs/ocfs2/suballoc.h linux-libre-3.8.13-gnu1/fs/ocfs2/suballoc.h
--- linux-libre-3.8-gnu1/fs/ocfs2/suballoc.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ocfs2/suballoc.h	2013-05-11 16:57:46.000000000 -0400
@@ -49,7 +49,7 @@ struct ocfs2_alloc_context {
 
 	/* these are used by the chain search */
 	u16    ac_chain;
-	int    ac_allow_chain_relink;
+	int    ac_disable_chain_relink;
 	group_search_t *ac_group_search;
 
 	u64    ac_last_group;
diff -druNp linux-libre-3.8-gnu1/fs/ocfs2/xattr.c linux-libre-3.8.13-gnu1/fs/ocfs2/xattr.c
--- linux-libre-3.8-gnu1/fs/ocfs2/xattr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ocfs2/xattr.c	2013-05-11 16:57:46.000000000 -0400
@@ -7189,7 +7189,7 @@ int ocfs2_init_security_and_acl(struct i
 	struct buffer_head *dir_bh = NULL;
 
 	ret = ocfs2_init_security_get(inode, dir, qstr, NULL);
-	if (!ret) {
+	if (ret) {
 		mlog_errno(ret);
 		goto leave;
 	}
diff -druNp linux-libre-3.8-gnu1/fs/pipe.c linux-libre-3.8.13-gnu1/fs/pipe.c
--- linux-libre-3.8-gnu1/fs/pipe.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/pipe.c	2013-05-11 16:57:46.000000000 -0400
@@ -863,6 +863,9 @@ pipe_rdwr_open(struct inode *inode, stru
 {
 	int ret = -ENOENT;
 
+	if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
+		return -EINVAL;
+
 	mutex_lock(&inode->i_mutex);
 
 	if (inode->i_pipe) {
diff -druNp linux-libre-3.8-gnu1/fs/pnode.c linux-libre-3.8.13-gnu1/fs/pnode.c
--- linux-libre-3.8-gnu1/fs/pnode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/pnode.c	2013-05-11 16:57:46.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/mnt_namespace.h>
 #include <linux/mount.h>
 #include <linux/fs.h>
+#include <linux/nsproxy.h>
 #include "internal.h"
 #include "pnode.h"
 
@@ -220,6 +221,7 @@ static struct mount *get_source(struct m
 int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 		    struct mount *source_mnt, struct list_head *tree_list)
 {
+	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
 	struct mount *m, *child;
 	int ret = 0;
 	struct mount *prev_dest_mnt = dest_mnt;
@@ -237,6 +239,10 @@ int propagate_mnt(struct mount *dest_mnt
 
 		source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
 
+		/* Notice when we are propagating across user namespaces */
+		if (m->mnt_ns->user_ns != user_ns)
+			type |= CL_UNPRIVILEGED;
+
 		child = copy_tree(source, source->mnt.mnt_root, type);
 		if (IS_ERR(child)) {
 			ret = PTR_ERR(child);
diff -druNp linux-libre-3.8-gnu1/fs/pnode.h linux-libre-3.8.13-gnu1/fs/pnode.h
--- linux-libre-3.8-gnu1/fs/pnode.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/pnode.h	2013-05-11 16:57:46.000000000 -0400
@@ -23,6 +23,7 @@
 #define CL_MAKE_SHARED 		0x08
 #define CL_PRIVATE 		0x10
 #define CL_SHARED_TO_SLAVE	0x20
+#define CL_UNPRIVILEGED		0x40
 
 static inline void set_mnt_shared(struct mount *mnt)
 {
diff -druNp linux-libre-3.8-gnu1/fs/proc/array.c linux-libre-3.8.13-gnu1/fs/proc/array.c
--- linux-libre-3.8-gnu1/fs/proc/array.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/proc/array.c	2013-05-11 16:57:46.000000000 -0400
@@ -143,6 +143,7 @@ static const char * const task_state_arr
 	"x (dead)",		/*  64 */
 	"K (wakekill)",		/* 128 */
 	"W (waking)",		/* 256 */
+	"P (parked)",		/* 512 */
 };
 
 static inline const char *get_task_state(struct task_struct *tsk)
diff -druNp linux-libre-3.8-gnu1/fs/proc/generic.c linux-libre-3.8.13-gnu1/fs/proc/generic.c
--- linux-libre-3.8-gnu1/fs/proc/generic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/proc/generic.c	2013-05-11 16:57:46.000000000 -0400
@@ -412,8 +412,7 @@ static const struct dentry_operations pr
 struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
 		struct dentry *dentry)
 {
-	struct inode *inode = NULL;
-	int error = -ENOENT;
+	struct inode *inode;
 
 	spin_lock(&proc_subdir_lock);
 	for (de = de->subdir; de ; de = de->next) {
@@ -422,22 +421,16 @@ struct dentry *proc_lookup_de(struct pro
 		if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
 			pde_get(de);
 			spin_unlock(&proc_subdir_lock);
-			error = -ENOMEM;
 			inode = proc_get_inode(dir->i_sb, de);
-			goto out_unlock;
+			if (!inode)
+				return ERR_PTR(-ENOMEM);
+			d_set_d_op(dentry, &proc_dentry_operations);
+			d_add(dentry, inode);
+			return NULL;
 		}
 	}
 	spin_unlock(&proc_subdir_lock);
-out_unlock:
-
-	if (inode) {
-		d_set_d_op(dentry, &proc_dentry_operations);
-		d_add(dentry, inode);
-		return NULL;
-	}
-	if (de)
-		pde_put(de);
-	return ERR_PTR(error);
+	return ERR_PTR(-ENOENT);
 }
 
 struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
diff -druNp linux-libre-3.8-gnu1/fs/proc/inode.c linux-libre-3.8.13-gnu1/fs/proc/inode.c
--- linux-libre-3.8-gnu1/fs/proc/inode.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/proc/inode.c	2013-05-11 16:57:46.000000000 -0400
@@ -445,12 +445,10 @@ static const struct file_operations proc
 
 struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
 {
-	struct inode * inode;
+	struct inode *inode = new_inode_pseudo(sb);
 
-	inode = iget_locked(sb, de->low_ino);
-	if (!inode)
-		return NULL;
-	if (inode->i_state & I_NEW) {
+	if (inode) {
+		inode->i_ino = de->low_ino;
 		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 		PROC_I(inode)->pde = de;
 
@@ -478,11 +476,10 @@ struct inode *proc_get_inode(struct supe
 				inode->i_fop = de->proc_fops;
 			}
 		}
-		unlock_new_inode(inode);
 	} else
 	       pde_put(de);
 	return inode;
-}			
+}
 
 int proc_fill_super(struct super_block *s)
 {
@@ -499,6 +496,5 @@ int proc_fill_super(struct super_block *
 		return 0;
 
 	printk("proc_read_super: get root inode failed\n");
-	pde_put(&proc_root);
 	return -ENOMEM;
 }
diff -druNp linux-libre-3.8-gnu1/fs/proc/namespaces.c linux-libre-3.8.13-gnu1/fs/proc/namespaces.c
--- linux-libre-3.8-gnu1/fs/proc/namespaces.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/proc/namespaces.c	2013-05-11 16:57:46.000000000 -0400
@@ -118,7 +118,7 @@ static void *proc_ns_follow_link(struct
 	struct super_block *sb = inode->i_sb;
 	struct proc_inode *ei = PROC_I(inode);
 	struct task_struct *task;
-	struct dentry *ns_dentry;
+	struct path ns_path;
 	void *error = ERR_PTR(-EACCES);
 
 	task = get_proc_task(inode);
@@ -128,14 +128,14 @@ static void *proc_ns_follow_link(struct
 	if (!ptrace_may_access(task, PTRACE_MODE_READ))
 		goto out_put_task;
 
-	ns_dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
-	if (IS_ERR(ns_dentry)) {
-		error = ERR_CAST(ns_dentry);
+	ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
+	if (IS_ERR(ns_path.dentry)) {
+		error = ERR_CAST(ns_path.dentry);
 		goto out_put_task;
 	}
 
-	dput(nd->path.dentry);
-	nd->path.dentry = ns_dentry;
+	ns_path.mnt = mntget(nd->path.mnt);
+	nd_jump_link(nd, &ns_path);
 	error = NULL;
 
 out_put_task:
diff -druNp linux-libre-3.8-gnu1/fs/proc/root.c linux-libre-3.8.13-gnu1/fs/proc/root.c
--- linux-libre-3.8-gnu1/fs/proc/root.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/proc/root.c	2013-05-11 16:57:46.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/user_namespace.h>
 #include <linux/mount.h>
 #include <linux/pid_namespace.h>
 #include <linux/parser.h>
@@ -108,6 +109,9 @@ static struct dentry *proc_mount(struct
 	} else {
 		ns = task_active_pid_ns(current);
 		options = data;
+
+		if (!current_user_ns()->may_mount_proc)
+			return ERR_PTR(-EPERM);
 	}
 
 	sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
diff -druNp linux-libre-3.8-gnu1/fs/pstore/platform.c linux-libre-3.8.13-gnu1/fs/pstore/platform.c
--- linux-libre-3.8-gnu1/fs/pstore/platform.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/pstore/platform.c	2013-05-11 16:57:46.000000000 -0400
@@ -96,6 +96,27 @@ static const char *get_reason_str(enum k
 	}
 }
 
+bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+	/*
+	 * In case of NMI path, pstore shouldn't be blocked
+	 * regardless of reason.
+	 */
+	if (in_nmi())
+		return true;
+
+	switch (reason) {
+	/* In panic case, other cpus are stopped by smp_send_stop(). */
+	case KMSG_DUMP_PANIC:
+	/* Emergency restart shouldn't be blocked by spin lock. */
+	case KMSG_DUMP_EMERG:
+		return true;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL_GPL(pstore_cannot_block_path);
+
 /*
  * callback from kmsg_dump. (s2,l2) has the most recently
  * written bytes, older bytes are in (s1,l1). Save as much
@@ -114,10 +135,12 @@ static void pstore_dump(struct kmsg_dump
 
 	why = get_reason_str(reason);
 
-	if (in_nmi()) {
-		is_locked = spin_trylock(&psinfo->buf_lock);
-		if (!is_locked)
-			pr_err("pstore dump routine blocked in NMI, may corrupt error record\n");
+	if (pstore_cannot_block_path(reason)) {
+		is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags);
+		if (!is_locked) {
+			pr_err("pstore dump routine blocked in %s path, may corrupt error record\n"
+				       , in_nmi() ? "NMI" : why);
+		}
 	} else
 		spin_lock_irqsave(&psinfo->buf_lock, flags);
 	oopscount++;
@@ -143,9 +166,9 @@ static void pstore_dump(struct kmsg_dump
 		total += hsize + len;
 		part++;
 	}
-	if (in_nmi()) {
+	if (pstore_cannot_block_path(reason)) {
 		if (is_locked)
-			spin_unlock(&psinfo->buf_lock);
+			spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 	} else
 		spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 }
diff -druNp linux-libre-3.8-gnu1/fs/reiserfs/xattr.c linux-libre-3.8.13-gnu1/fs/reiserfs/xattr.c
--- linux-libre-3.8-gnu1/fs/reiserfs/xattr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/reiserfs/xattr.c	2013-05-11 16:57:46.000000000 -0400
@@ -187,8 +187,8 @@ fill_with_dentries(void *buf, const char
 	if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
 		return -ENOSPC;
 
-	if (name[0] == '.' && (name[1] == '\0' ||
-			       (name[1] == '.' && name[2] == '\0')))
+	if (name[0] == '.' && (namelen < 2 ||
+			       (namelen == 2 && name[1] == '.')))
 		return 0;
 
 	dentry = lookup_one_len(name, dbuf->xadir, namelen);
diff -druNp linux-libre-3.8-gnu1/fs/sysfs/dir.c linux-libre-3.8.13-gnu1/fs/sysfs/dir.c
--- linux-libre-3.8-gnu1/fs/sysfs/dir.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/sysfs/dir.c	2013-05-11 16:57:46.000000000 -0400
@@ -1012,6 +1012,7 @@ static int sysfs_readdir(struct file * f
 	enum kobj_ns_type type;
 	const void *ns;
 	ino_t ino;
+	loff_t off;
 
 	type = sysfs_ns_type(parent_sd);
 	ns = sysfs_info(dentry->d_sb)->ns[type];
@@ -1020,6 +1021,8 @@ static int sysfs_readdir(struct file * f
 		ino = parent_sd->s_ino;
 		if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0)
 			filp->f_pos++;
+		else
+			return 0;
 	}
 	if (filp->f_pos == 1) {
 		if (parent_sd->s_parent)
@@ -1028,8 +1031,11 @@ static int sysfs_readdir(struct file * f
 			ino = parent_sd->s_ino;
 		if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
 			filp->f_pos++;
+		else
+			return 0;
 	}
 	mutex_lock(&sysfs_mutex);
+	off = filp->f_pos;
 	for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
 	     pos;
 	     pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
@@ -1041,27 +1047,43 @@ static int sysfs_readdir(struct file * f
 		len = strlen(name);
 		ino = pos->s_ino;
 		type = dt_type(pos);
-		filp->f_pos = pos->s_hash;
+		off = filp->f_pos = pos->s_hash;
 		filp->private_data = sysfs_get(pos);
 
 		mutex_unlock(&sysfs_mutex);
-		ret = filldir(dirent, name, len, filp->f_pos, ino, type);
+		ret = filldir(dirent, name, len, off, ino, type);
 		mutex_lock(&sysfs_mutex);
 		if (ret < 0)
 			break;
 	}
 	mutex_unlock(&sysfs_mutex);
-	if ((filp->f_pos > 1) && !pos) { /* EOF */
-		filp->f_pos = INT_MAX;
+
+	/* don't reference last entry if its refcount is dropped */
+	if (!pos) {
 		filp->private_data = NULL;
+
+		/* EOF and not changed as 0 or 1 in read/write path */
+		if (off == filp->f_pos && off > 1)
+			filp->f_pos = INT_MAX;
 	}
 	return 0;
 }
 
+static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	loff_t ret;
+
+	mutex_lock(&inode->i_mutex);
+	ret = generic_file_llseek(file, offset, whence);
+	mutex_unlock(&inode->i_mutex);
+
+	return ret;
+}
 
 const struct file_operations sysfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= sysfs_readdir,
 	.release	= sysfs_dir_release,
-	.llseek		= generic_file_llseek,
+	.llseek		= sysfs_dir_llseek,
 };
diff -druNp linux-libre-3.8-gnu1/fs/sysfs/mount.c linux-libre-3.8.13-gnu1/fs/sysfs/mount.c
--- linux-libre-3.8-gnu1/fs/sysfs/mount.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/sysfs/mount.c	2013-05-11 16:57:46.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/magic.h>
 #include <linux/slab.h>
+#include <linux/user_namespace.h>
 
 #include "sysfs.h"
 
@@ -111,6 +112,9 @@ static struct dentry *sysfs_mount(struct
 	struct super_block *sb;
 	int error;
 
+	if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs)
+		return ERR_PTR(-EPERM);
+
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return ERR_PTR(-ENOMEM);
diff -druNp linux-libre-3.8-gnu1/fs/ubifs/orphan.c linux-libre-3.8.13-gnu1/fs/ubifs/orphan.c
--- linux-libre-3.8-gnu1/fs/ubifs/orphan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ubifs/orphan.c	2013-05-11 16:57:46.000000000 -0400
@@ -126,13 +126,14 @@ void ubifs_delete_orphan(struct ubifs_in
 		else if (inum > o->inum)
 			p = p->rb_right;
 		else {
-			if (o->dnext) {
+			if (o->del) {
 				spin_unlock(&c->orphan_lock);
 				dbg_gen("deleted twice ino %lu",
 					(unsigned long)inum);
 				return;
 			}
-			if (o->cnext) {
+			if (o->cmt) {
+				o->del = 1;
 				o->dnext = c->orph_dnext;
 				c->orph_dnext = o;
 				spin_unlock(&c->orphan_lock);
@@ -172,7 +173,9 @@ int ubifs_orphan_start_commit(struct ubi
 	last = &c->orph_cnext;
 	list_for_each_entry(orphan, &c->orph_new, new_list) {
 		ubifs_assert(orphan->new);
+		ubifs_assert(!orphan->cmt);
 		orphan->new = 0;
+		orphan->cmt = 1;
 		*last = orphan;
 		last = &orphan->cnext;
 	}
@@ -299,7 +302,9 @@ static int write_orph_node(struct ubifs_
 	cnext = c->orph_cnext;
 	for (i = 0; i < cnt; i++) {
 		orphan = cnext;
+		ubifs_assert(orphan->cmt);
 		orph->inos[i] = cpu_to_le64(orphan->inum);
+		orphan->cmt = 0;
 		cnext = orphan->cnext;
 		orphan->cnext = NULL;
 	}
@@ -378,6 +383,7 @@ static int consolidate(struct ubifs_info
 		list_for_each_entry(orphan, &c->orph_list, list) {
 			if (orphan->new)
 				continue;
+			orphan->cmt = 1;
 			*last = orphan;
 			last = &orphan->cnext;
 			cnt += 1;
@@ -442,6 +448,7 @@ static void erase_deleted(struct ubifs_i
 		orphan = dnext;
 		dnext = orphan->dnext;
 		ubifs_assert(!orphan->new);
+		ubifs_assert(orphan->del);
 		rb_erase(&orphan->rb, &c->orph_tree);
 		list_del(&orphan->list);
 		c->tot_orphans -= 1;
@@ -531,6 +538,7 @@ static int insert_dead_orphan(struct ubi
 	rb_link_node(&orphan->rb, parent, p);
 	rb_insert_color(&orphan->rb, &c->orph_tree);
 	list_add_tail(&orphan->list, &c->orph_list);
+	orphan->del = 1;
 	orphan->dnext = c->orph_dnext;
 	c->orph_dnext = orphan;
 	dbg_mnt("ino %lu, new %d, tot %d", (unsigned long)inum,
diff -druNp linux-libre-3.8-gnu1/fs/ubifs/super.c linux-libre-3.8.13-gnu1/fs/ubifs/super.c
--- linux-libre-3.8-gnu1/fs/ubifs/super.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ubifs/super.c	2013-05-11 16:57:46.000000000 -0400
@@ -1568,6 +1568,12 @@ static int ubifs_remount_rw(struct ubifs
 	c->remounting_rw = 1;
 	c->ro_mount = 0;
 
+	if (c->space_fixup) {
+		err = ubifs_fixup_free_space(c);
+		if (err)
+			return err;
+	}
+
 	err = check_free_space(c);
 	if (err)
 		goto out;
@@ -1684,12 +1690,6 @@ static int ubifs_remount_rw(struct ubifs
 		err = dbg_check_space_info(c);
 	}
 
-	if (c->space_fixup) {
-		err = ubifs_fixup_free_space(c);
-		if (err)
-			goto out;
-	}
-
 	mutex_unlock(&c->umount_mutex);
 	return err;
 
diff -druNp linux-libre-3.8-gnu1/fs/ubifs/ubifs.h linux-libre-3.8.13-gnu1/fs/ubifs/ubifs.h
--- linux-libre-3.8-gnu1/fs/ubifs/ubifs.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/ubifs/ubifs.h	2013-05-11 16:57:46.000000000 -0400
@@ -904,6 +904,8 @@ struct ubifs_budget_req {
  * @dnext: next orphan to delete
  * @inum: inode number
  * @new: %1 => added since the last commit, otherwise %0
+ * @cmt: %1 => commit pending, otherwise %0
+ * @del: %1 => delete pending, otherwise %0
  */
 struct ubifs_orphan {
 	struct rb_node rb;
@@ -912,7 +914,9 @@ struct ubifs_orphan {
 	struct ubifs_orphan *cnext;
 	struct ubifs_orphan *dnext;
 	ino_t inum;
-	int new;
+	unsigned new:1;
+	unsigned cmt:1;
+	unsigned del:1;
 };
 
 /**
diff -druNp linux-libre-3.8-gnu1/fs/udf/udf_sb.h linux-libre-3.8.13-gnu1/fs/udf/udf_sb.h
--- linux-libre-3.8-gnu1/fs/udf/udf_sb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/udf/udf_sb.h	2013-05-11 16:57:46.000000000 -0400
@@ -82,7 +82,7 @@ struct udf_virtual_data {
 struct udf_bitmap {
 	__u32			s_extLength;
 	__u32			s_extPosition;
-	__u16			s_nr_groups;
+	int			s_nr_groups;
 	struct buffer_head 	**s_block_bitmap;
 };
 
diff -druNp linux-libre-3.8-gnu1/fs/xfs/xfs_bmap.c linux-libre-3.8.13-gnu1/fs/xfs/xfs_bmap.c
--- linux-libre-3.8-gnu1/fs/xfs/xfs_bmap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/fs/xfs/xfs_bmap.c	2013-05-11 16:57:46.000000000 -0400
@@ -147,7 +147,10 @@ xfs_bmap_local_to_extents(
 	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
 	xfs_extlen_t	total,		/* total blocks needed by transaction */
 	int		*logflagsp,	/* inode logging flags */
-	int		whichfork);	/* data or attr fork */
+	int		whichfork,	/* data or attr fork */
+	void		(*init_fn)(struct xfs_buf *bp,
+				   struct xfs_inode *ip,
+				   struct xfs_ifork *ifp));
 
 /*
  * Search the extents list for the inode, for the extent containing bno.
@@ -357,7 +360,42 @@ xfs_bmap_add_attrfork_extents(
 }
 
 /*
- * Called from xfs_bmap_add_attrfork to handle local format files.
+ * Block initialisation functions for local to extent format conversion.
+ * As these get more complex, they will be moved to the relevant files,
+ * but for now they are too simple to worry about.
+ */
+STATIC void
+xfs_bmap_local_to_extents_init_fn(
+	struct xfs_buf		*bp,
+	struct xfs_inode	*ip,
+	struct xfs_ifork	*ifp)
+{
+	bp->b_ops = &xfs_bmbt_buf_ops;
+	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+}
+
+STATIC void
+xfs_symlink_local_to_remote(
+	struct xfs_buf		*bp,
+	struct xfs_inode	*ip,
+	struct xfs_ifork	*ifp)
+{
+	/* remote symlink blocks are not verifiable until CRCs come along */
+	bp->b_ops = NULL;
+	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+}
+
+/*
+ * Called from xfs_bmap_add_attrfork to handle local format files. Each
+ * different data fork content type needs a different callout to do the
+ * conversion. Some are basic and only require special block initialisation
+ * callouts for the data formating, others (directories) are so specialised they
+ * handle everything themselves.
+ *
+ * XXX (dgc): investigate whether directory conversion can use the generic
+ * formatting callout. It should be possible - it's just a very complex
+ * formatter. it would also require passing the transaction through to the init
+ * function.
  */
 STATIC int					/* error */
 xfs_bmap_add_attrfork_local(
@@ -368,25 +406,29 @@ xfs_bmap_add_attrfork_local(
 	int			*flags)		/* inode logging flags */
 {
 	xfs_da_args_t		dargs;		/* args for dir/attr code */
-	int			error;		/* error return value */
-	xfs_mount_t		*mp;		/* mount structure pointer */
 
 	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
 		return 0;
+
 	if (S_ISDIR(ip->i_d.di_mode)) {
-		mp = ip->i_mount;
 		memset(&dargs, 0, sizeof(dargs));
 		dargs.dp = ip;
 		dargs.firstblock = firstblock;
 		dargs.flist = flist;
-		dargs.total = mp->m_dirblkfsbs;
+		dargs.total = ip->i_mount->m_dirblkfsbs;
 		dargs.whichfork = XFS_DATA_FORK;
 		dargs.trans = tp;
-		error = xfs_dir2_sf_to_block(&dargs);
-	} else
-		error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
-			XFS_DATA_FORK);
-	return error;
+		return xfs_dir2_sf_to_block(&dargs);
+	}
+
+	if (S_ISLNK(ip->i_d.di_mode))
+		return xfs_bmap_local_to_extents(tp, ip, firstblock, 1,
+						 flags, XFS_DATA_FORK,
+						 xfs_symlink_local_to_remote);
+
+	return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
+					 XFS_DATA_FORK,
+					 xfs_bmap_local_to_extents_init_fn);
 }
 
 /*
@@ -3221,7 +3263,10 @@ xfs_bmap_local_to_extents(
 	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
 	xfs_extlen_t	total,		/* total blocks needed by transaction */
 	int		*logflagsp,	/* inode logging flags */
-	int		whichfork)	/* data or attr fork */
+	int		whichfork,
+	void		(*init_fn)(struct xfs_buf *bp,
+				   struct xfs_inode *ip,
+				   struct xfs_ifork *ifp))
 {
 	int		error;		/* error return value */
 	int		flags;		/* logging flags returned */
@@ -3241,12 +3286,12 @@ xfs_bmap_local_to_extents(
 		xfs_buf_t	*bp;	/* buffer for extent block */
 		xfs_bmbt_rec_host_t *ep;/* extent record pointer */
 
+		ASSERT((ifp->if_flags &
+			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
 		memset(&args, 0, sizeof(args));
 		args.tp = tp;
 		args.mp = ip->i_mount;
 		args.firstblock = *firstblock;
-		ASSERT((ifp->if_flags &
-			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
 		/*
 		 * Allocate a block.  We know we need only one, since the
 		 * file currently fits in an inode.
@@ -3262,17 +3307,20 @@ xfs_bmap_local_to_extents(
 		args.mod = args.minleft = args.alignment = args.wasdel =
 			args.isfl = args.minalignslop = 0;
 		args.minlen = args.maxlen = args.prod = 1;
-		if ((error = xfs_alloc_vextent(&args)))
+		error = xfs_alloc_vextent(&args);
+		if (error)
 			goto done;
-		/*
-		 * Can't fail, the space was reserved.
-		 */
+
+		/* Can't fail, the space was reserved. */
 		ASSERT(args.fsbno != NULLFSBLOCK);
 		ASSERT(args.len == 1);
 		*firstblock = args.fsbno;
 		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
-		bp->b_ops = &xfs_bmbt_buf_ops;
-		memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+
+		/* initialise the block and copy the data */
+		init_fn(bp, ip, ifp);
+
+		/* account for the change in fork size and log everything */
 		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
 		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
 		xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
@@ -4919,8 +4967,32 @@ xfs_bmapi_write(
 	XFS_STATS_INC(xs_blk_mapw);
 
 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+		/*
+		 * XXX (dgc): This assumes we are only called for inodes that
+		 * contain content neutral data in local format. Anything that
+		 * contains caller-specific data in local format that needs
+		 * transformation to move to a block format needs to do the
+		 * conversion to extent format itself.
+		 *
+		 * Directory data forks and attribute forks handle this
+		 * themselves, but with the addition of metadata verifiers every
+		 * data fork in local format now contains caller specific data
+		 * and as such conversion through this function is likely to be
+		 * broken.
+		 *
+		 * The only likely user of this branch is for remote symlinks,
+		 * but we cannot overwrite the data fork contents of the symlink
+		 * (EEXIST occurs higher up the stack) and so it will never go
+		 * from local format to extent format here. Hence I don't think
+		 * this branch is ever executed intentionally and we should
+		 * consider removing it and asserting that xfs_bmapi_write()
+		 * cannot be called directly on local format forks. i.e. callers
+		 * are completely responsible for local to extent format
+		 * conversion, not xfs_bmapi_write().
+		 */
 		error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
-						  &bma.logflags, whichfork);
+					&bma.logflags, whichfork,
+					xfs_bmap_local_to_extents_init_fn);
 		if (error)
 			goto error0;
 	}
diff -druNp linux-libre-3.8-gnu1/include/asm-generic/pgtable.h linux-libre-3.8.13-gnu1/include/asm-generic/pgtable.h
--- linux-libre-3.8-gnu1/include/asm-generic/pgtable.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/asm-generic/pgtable.h	2013-05-11 16:57:46.000000000 -0400
@@ -7,6 +7,16 @@
 #include <linux/mm_types.h>
 #include <linux/bug.h>
 
+/*
+ * On almost all architectures and configurations, 0 can be used as the
+ * upper ceiling to free_pgtables(): on many architectures it has the same
+ * effect as using TASK_SIZE.  However, there is one configuration which
+ * must impose a more careful limit, to avoid freeing kernel pgtables.
+ */
+#ifndef USER_PGTABLES_CEILING
+#define USER_PGTABLES_CEILING	0UL
+#endif
+
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 extern int ptep_set_access_flags(struct vm_area_struct *vma,
 				 unsigned long address, pte_t *ptep,
diff -druNp linux-libre-3.8-gnu1/include/asm-generic/tlb.h linux-libre-3.8.13-gnu1/include/asm-generic/tlb.h
--- linux-libre-3.8-gnu1/include/asm-generic/tlb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/asm-generic/tlb.h	2013-05-11 16:57:46.000000000 -0400
@@ -99,7 +99,12 @@ struct mmu_gather {
 	unsigned int		need_flush : 1,	/* Did free PTEs */
 				fast_mode  : 1; /* No batching   */
 
-	unsigned int		fullmm;
+	/* we are in the middle of an operation to clear
+	 * a full mm and can make some optimizations */
+	unsigned int		fullmm : 1,
+	/* we have performed an operation which
+	 * requires a complete flush of the tlb */
+				need_flush_all : 1;
 
 	struct mmu_gather_batch *active;
 	struct mmu_gather_batch	local;
diff -druNp linux-libre-3.8-gnu1/include/drm/drm_pciids.h linux-libre-3.8.13-gnu1/include/drm/drm_pciids.h
--- linux-libre-3.8-gnu1/include/drm/drm_pciids.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/drm/drm_pciids.h	2013-05-11 16:57:46.000000000 -0400
@@ -227,6 +227,7 @@
 	{0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6821, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6822, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6823, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6824, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -234,11 +235,13 @@
 	{0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
@@ -568,7 +571,11 @@
 	{0x1002, 0x9908, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9909, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x990A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-	{0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x990B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x990C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x990D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x990E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9910, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9913, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9917, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
@@ -579,6 +586,15 @@
 	{0x1002, 0x9992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9993, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9994, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9996, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9998, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9999, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x999A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x999B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x999C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x999D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
diff -druNp linux-libre-3.8-gnu1/include/drm/drmP.h linux-libre-3.8.13-gnu1/include/drm/drmP.h
--- linux-libre-3.8-gnu1/include/drm/drmP.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/drm/drmP.h	2013-05-11 16:57:46.000000000 -0400
@@ -1559,9 +1559,8 @@ extern void drm_prime_gem_destroy(struct
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
-int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
-int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
-void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
 
 int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
 int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
diff -druNp linux-libre-3.8-gnu1/include/linux/ata.h linux-libre-3.8.13-gnu1/include/linux/ata.h
--- linux-libre-3.8-gnu1/include/linux/ata.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/ata.h	2013-05-11 16:57:46.000000000 -0400
@@ -954,7 +954,7 @@ static inline int atapi_cdb_len(const u1
 	}
 }
 
-static inline bool atapi_command_packet_set(const u16 *dev_id)
+static inline int atapi_command_packet_set(const u16 *dev_id)
 {
 	return (dev_id[ATA_ID_CONFIG] >> 8) & 0x1f;
 }
diff -druNp linux-libre-3.8-gnu1/include/linux/blkdev.h linux-libre-3.8.13-gnu1/include/linux/blkdev.h
--- linux-libre-3.8-gnu1/include/linux/blkdev.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/blkdev.h	2013-05-11 16:57:46.000000000 -0400
@@ -836,7 +836,7 @@ static inline unsigned int blk_queue_get
 						     unsigned int cmd_flags)
 {
 	if (unlikely(cmd_flags & REQ_DISCARD))
-		return q->limits.max_discard_sectors;
+		return min(q->limits.max_discard_sectors, UINT_MAX >> 9);
 
 	if (unlikely(cmd_flags & REQ_WRITE_SAME))
 		return q->limits.max_write_same_sectors;
diff -druNp linux-libre-3.8-gnu1/include/linux/capability.h linux-libre-3.8.13-gnu1/include/linux/capability.h
--- linux-libre-3.8-gnu1/include/linux/capability.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/capability.h	2013-05-11 16:57:46.000000000 -0400
@@ -35,6 +35,7 @@ struct cpu_vfs_cap_data {
 #define _KERNEL_CAP_T_SIZE     (sizeof(kernel_cap_t))
 
 
+struct file;
 struct inode;
 struct dentry;
 struct user_namespace;
@@ -211,6 +212,7 @@ extern bool capable(int cap);
 extern bool ns_capable(struct user_namespace *ns, int cap);
 extern bool nsown_capable(int cap);
 extern bool inode_capable(const struct inode *inode, int cap);
+extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff -druNp linux-libre-3.8-gnu1/include/linux/cgroup.h linux-libre-3.8.13-gnu1/include/linux/cgroup.h
--- linux-libre-3.8-gnu1/include/linux/cgroup.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/cgroup.h	2013-05-11 16:57:46.000000000 -0400
@@ -303,9 +303,6 @@ struct cftype {
 	/* CFTYPE_* flags */
 	unsigned int flags;
 
-	/* file xattrs */
-	struct simple_xattrs xattrs;
-
 	int (*open)(struct inode *inode, struct file *file);
 	ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
 			struct file *file,
diff -druNp linux-libre-3.8-gnu1/include/linux/console.h linux-libre-3.8.13-gnu1/include/linux/console.h
--- linux-libre-3.8-gnu1/include/linux/console.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/console.h	2013-05-11 16:57:46.000000000 -0400
@@ -77,7 +77,9 @@ extern const struct consw prom_con;	/* S
 int con_is_bound(const struct consw *csw);
 int register_con_driver(const struct consw *csw, int first, int last);
 int unregister_con_driver(const struct consw *csw);
+int do_unregister_con_driver(const struct consw *csw);
 int take_over_console(const struct consw *sw, int first, int last, int deflt);
+int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
 void give_up_console(const struct consw *sw);
 #ifdef CONFIG_HW_CONSOLE
 int con_debug_enter(struct vc_data *vc);
diff -druNp linux-libre-3.8-gnu1/include/linux/device-mapper.h linux-libre-3.8.13-gnu1/include/linux/device-mapper.h
--- linux-libre-3.8-gnu1/include/linux/device-mapper.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/device-mapper.h	2013-05-11 16:57:46.000000000 -0400
@@ -68,8 +68,8 @@ typedef void (*dm_postsuspend_fn) (struc
 typedef int (*dm_preresume_fn) (struct dm_target *ti);
 typedef void (*dm_resume_fn) (struct dm_target *ti);
 
-typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
-			     unsigned status_flags, char *result, unsigned maxlen);
+typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
+			      unsigned status_flags, char *result, unsigned maxlen);
 
 typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
 
diff -druNp linux-libre-3.8-gnu1/include/linux/fs_struct.h linux-libre-3.8.13-gnu1/include/linux/fs_struct.h
--- linux-libre-3.8-gnu1/include/linux/fs_struct.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/fs_struct.h	2013-05-11 16:57:46.000000000 -0400
@@ -50,4 +50,6 @@ static inline void get_fs_root_and_pwd(s
 	spin_unlock(&fs->lock);
 }
 
+extern bool current_chrooted(void);
+
 #endif /* _LINUX_FS_STRUCT_H */
diff -druNp linux-libre-3.8-gnu1/include/linux/ftrace.h linux-libre-3.8.13-gnu1/include/linux/ftrace.h
--- linux-libre-3.8-gnu1/include/linux/ftrace.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/ftrace.h	2013-05-11 16:57:46.000000000 -0400
@@ -394,7 +394,6 @@ ssize_t ftrace_filter_write(struct file
 			    size_t cnt, loff_t *ppos);
 ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
 			     size_t cnt, loff_t *ppos);
-loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence);
 int ftrace_regex_release(struct inode *inode, struct file *file);
 
 void __init
@@ -567,6 +566,8 @@ static inline int
 ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; }
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+loff_t ftrace_filter_lseek(struct file *file, loff_t offset, int whence);
+
 /* totally disable ftrace - can not re-enable after this */
 void ftrace_kill(void);
 
diff -druNp linux-libre-3.8-gnu1/include/linux/hugetlb.h linux-libre-3.8.13-gnu1/include/linux/hugetlb.h
--- linux-libre-3.8-gnu1/include/linux/hugetlb.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/hugetlb.h	2013-05-11 16:57:46.000000000 -0400
@@ -185,8 +185,7 @@ static inline struct hugetlbfs_sb_info *
 
 extern const struct file_operations hugetlbfs_file_operations;
 extern const struct vm_operations_struct hugetlb_vm_ops;
-struct file *hugetlb_file_setup(const char *name, unsigned long addr,
-				size_t size, vm_flags_t acct,
+struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct,
 				struct user_struct **user, int creat_flags,
 				int page_size_log);
 
@@ -205,8 +204,8 @@ static inline int is_file_hugepages(stru
 
 #define is_file_hugepages(file)			0
 static inline struct file *
-hugetlb_file_setup(const char *name, unsigned long addr, size_t size,
-		vm_flags_t acctflag, struct user_struct **user, int creat_flags,
+hugetlb_file_setup(const char *name, size_t size, vm_flags_t acctflag,
+		struct user_struct **user, int creat_flags,
 		int page_size_log)
 {
 	return ERR_PTR(-ENOSYS);
@@ -284,6 +283,13 @@ static inline struct hstate *hstate_file
 	return hstate_inode(f->f_dentry->d_inode);
 }
 
+static inline struct hstate *hstate_sizelog(int page_size_log)
+{
+	if (!page_size_log)
+		return &default_hstate;
+	return size_to_hstate(1 << page_size_log);
+}
+
 static inline struct hstate *hstate_vma(struct vm_area_struct *vma)
 {
 	return hstate_file(vma->vm_file);
@@ -348,11 +354,12 @@ static inline int hstate_index(struct hs
 	return h - hstates;
 }
 
-#else
+#else	/* CONFIG_HUGETLB_PAGE */
 struct hstate {};
 #define alloc_huge_page_node(h, nid) NULL
 #define alloc_bootmem_huge_page(h) NULL
 #define hstate_file(f) NULL
+#define hstate_sizelog(s) NULL
 #define hstate_vma(v) NULL
 #define hstate_inode(i) NULL
 #define huge_page_size(h) PAGE_SIZE
@@ -367,6 +374,6 @@ static inline unsigned int pages_per_hug
 }
 #define hstate_index_to_shift(index) 0
 #define hstate_index(h) 0
-#endif
+#endif	/* CONFIG_HUGETLB_PAGE */
 
 #endif /* _LINUX_HUGETLB_H */
diff -druNp linux-libre-3.8-gnu1/include/linux/if_vlan.h linux-libre-3.8.13-gnu1/include/linux/if_vlan.h
--- linux-libre-3.8-gnu1/include/linux/if_vlan.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/if_vlan.h	2013-05-11 16:57:46.000000000 -0400
@@ -331,7 +331,7 @@ static inline void vlan_set_encap_proto(
 					struct vlan_hdr *vhdr)
 {
 	__be16 proto;
-	unsigned char *rawp;
+	unsigned short *rawp;
 
 	/*
 	 * Was a VLAN packet, grab the encapsulated protocol, which the layer
@@ -344,8 +344,8 @@ static inline void vlan_set_encap_proto(
 		return;
 	}
 
-	rawp = skb->data;
-	if (*(unsigned short *) rawp == 0xFFFF)
+	rawp = (unsigned short *)(vhdr + 1);
+	if (*rawp == 0xFFFF)
 		/*
 		 * This is a magic hack to spot IPX packets. Older Novell
 		 * breaks the protocol design and runs IPX over 802.3 without
diff -druNp linux-libre-3.8-gnu1/include/linux/ipc_namespace.h linux-libre-3.8.13-gnu1/include/linux/ipc_namespace.h
--- linux-libre-3.8-gnu1/include/linux/ipc_namespace.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/ipc_namespace.h	2013-05-11 16:57:46.000000000 -0400
@@ -43,8 +43,8 @@ struct ipc_namespace {
 
 	size_t		shm_ctlmax;
 	size_t		shm_ctlall;
+	unsigned long	shm_tot;
 	int		shm_ctlmni;
-	int		shm_tot;
 	/*
 	 * Defines whether IPC_RMID is forced for _all_ shm segments regardless
 	 * of shmctl()
diff -druNp linux-libre-3.8-gnu1/include/linux/jbd2.h linux-libre-3.8.13-gnu1/include/linux/jbd2.h
--- linux-libre-3.8-gnu1/include/linux/jbd2.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/jbd2.h	2013-05-11 16:57:46.000000000 -0400
@@ -498,6 +498,7 @@ struct transaction_s
 		T_COMMIT,
 		T_COMMIT_DFLUSH,
 		T_COMMIT_JFLUSH,
+		T_COMMIT_CALLBACK,
 		T_FINISHED
 	}			t_state;
 
@@ -1210,6 +1211,7 @@ int __jbd2_log_start_commit(journal_t *j
 int jbd2_journal_start_commit(journal_t *journal, tid_t *tid);
 int jbd2_journal_force_commit_nested(journal_t *journal);
 int jbd2_log_wait_commit(journal_t *journal, tid_t tid);
+int jbd2_complete_transaction(journal_t *journal, tid_t tid);
 int jbd2_log_do_checkpoint(journal_t *journal);
 int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid);
 
diff -druNp linux-libre-3.8-gnu1/include/linux/kvm_host.h linux-libre-3.8.13-gnu1/include/linux/kvm_host.h
--- linux-libre-3.8-gnu1/include/linux/kvm_host.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/kvm_host.h	2013-05-11 16:57:46.000000000 -0400
@@ -511,7 +511,7 @@ int kvm_write_guest(struct kvm *kvm, gpa
 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 			   void *data, unsigned long len);
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-			      gpa_t gpa);
+			      gpa_t gpa, unsigned long len);
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
diff -druNp linux-libre-3.8-gnu1/include/linux/kvm_types.h linux-libre-3.8.13-gnu1/include/linux/kvm_types.h
--- linux-libre-3.8-gnu1/include/linux/kvm_types.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/kvm_types.h	2013-05-11 16:57:46.000000000 -0400
@@ -71,6 +71,7 @@ struct gfn_to_hva_cache {
 	u64 generation;
 	gpa_t gpa;
 	unsigned long hva;
+	unsigned long len;
 	struct kvm_memory_slot *memslot;
 };
 
diff -druNp linux-libre-3.8-gnu1/include/linux/libata.h linux-libre-3.8.13-gnu1/include/linux/libata.h
--- linux-libre-3.8-gnu1/include/linux/libata.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/libata.h	2013-05-11 16:57:46.000000000 -0400
@@ -398,6 +398,7 @@ enum {
 	ATA_HORKAGE_NOSETXFER	= (1 << 14),	/* skip SETXFER, SATA only */
 	ATA_HORKAGE_BROKEN_FPDMA_AA	= (1 << 15),	/* skip AA */
 	ATA_HORKAGE_DUMP_ID	= (1 << 16),	/* dump IDENTIFY data */
+	ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),	/* Set max sects to 65535 */
 
 	 /* DMA mask for user DMA control: User visible values; DO NOT
 	    renumber */
diff -druNp linux-libre-3.8-gnu1/include/linux/llist.h linux-libre-3.8.13-gnu1/include/linux/llist.h
--- linux-libre-3.8-gnu1/include/linux/llist.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/llist.h	2013-05-11 16:57:46.000000000 -0400
@@ -125,31 +125,6 @@ static inline void init_llist_head(struc
 	     (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))
 
 /**
- * llist_for_each_entry_safe - iterate safely against remove over some entries
- * of lock-less list of given type.
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as a temporary storage.
- * @node:	the fist entry of deleted list entries.
- * @member:	the name of the llist_node with the struct.
- *
- * In general, some entries of the lock-less list can be traversed
- * safely only after being removed from list, so start with an entry
- * instead of list head. This variant allows removal of entries
- * as we iterate.
- *
- * If being used on entries deleted from lock-less list directly, the
- * traverse order is from the newest to the oldest added entry.  If
- * you want to traverse from the oldest to the newest, you must
- * reverse the order by yourself before traversing.
- */
-#define llist_for_each_entry_safe(pos, n, node, member)		\
-	for ((pos) = llist_entry((node), typeof(*(pos)), member),	\
-	     (n) = (pos)->member.next;					\
-	     &(pos)->member != NULL;					\
-	     (pos) = llist_entry(n, typeof(*(pos)), member),		\
-	     (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL)
-
-/**
  * llist_empty - tests whether a lock-less list is empty
  * @head:	the list to test
  *
diff -druNp linux-libre-3.8-gnu1/include/linux/mfd/rtsx_pci.h linux-libre-3.8.13-gnu1/include/linux/mfd/rtsx_pci.h
--- linux-libre-3.8-gnu1/include/linux/mfd/rtsx_pci.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/mfd/rtsx_pci.h	2013-05-11 16:57:46.000000000 -0400
@@ -735,6 +735,7 @@ struct rtsx_pcr {
 
 	unsigned int			card_inserted;
 	unsigned int			card_removed;
+	unsigned int			card_exist;
 
 	struct delayed_work		carddet_work;
 	struct delayed_work		idle_work;
@@ -799,6 +800,7 @@ int rtsx_pci_switch_clock(struct rtsx_pc
 		u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
 int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
 int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card);
 int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage);
 unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
 void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
diff -druNp linux-libre-3.8-gnu1/include/linux/mm.h linux-libre-3.8.13-gnu1/include/linux/mm.h
--- linux-libre-3.8-gnu1/include/linux/mm.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/mm.h	2013-05-11 16:57:46.000000000 -0400
@@ -1623,6 +1623,8 @@ int vm_insert_pfn(struct vm_area_struct
 			unsigned long pfn);
 int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
 			unsigned long pfn);
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len);
+
 
 struct page *follow_page(struct vm_area_struct *, unsigned long address,
 			unsigned int foll_flags);
diff -druNp linux-libre-3.8-gnu1/include/linux/mount.h linux-libre-3.8.13-gnu1/include/linux/mount.h
--- linux-libre-3.8-gnu1/include/linux/mount.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/mount.h	2013-05-11 16:57:46.000000000 -0400
@@ -47,6 +47,8 @@ struct mnt_namespace;
 
 #define MNT_INTERNAL	0x4000
 
+#define MNT_LOCK_READONLY	0x400000
+
 struct vfsmount {
 	struct dentry *mnt_root;	/* root of the mounted tree */
 	struct super_block *mnt_sb;	/* pointer to superblock */
diff -druNp linux-libre-3.8-gnu1/include/linux/mtd/nand.h linux-libre-3.8.13-gnu1/include/linux/mtd/nand.h
--- linux-libre-3.8-gnu1/include/linux/mtd/nand.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/mtd/nand.h	2013-05-11 16:57:46.000000000 -0400
@@ -187,6 +187,13 @@ typedef enum {
  * This happens with the Renesas AG-AND chips, possibly others.
  */
 #define BBT_AUTO_REFRESH	0x00000080
+/*
+ * Chip requires ready check on read (for auto-incremented sequential read).
+ * True only for small page devices; large page devices do not support
+ * autoincrement.
+ */
+#define NAND_NEED_READRDY	0x00000100
+
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
 
diff -druNp linux-libre-3.8-gnu1/include/linux/netdevice.h linux-libre-3.8.13-gnu1/include/linux/netdevice.h
--- linux-libre-3.8-gnu1/include/linux/netdevice.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/netdevice.h	2013-05-11 16:57:46.000000000 -0400
@@ -208,9 +208,9 @@ struct netdev_hw_addr {
 #define NETDEV_HW_ADDR_T_SLAVE		3
 #define NETDEV_HW_ADDR_T_UNICAST	4
 #define NETDEV_HW_ADDR_T_MULTICAST	5
-	bool			synced;
 	bool			global_use;
 	int			refcount;
+	int			synced;
 	struct rcu_head		rcu_head;
 };
 
diff -druNp linux-libre-3.8-gnu1/include/linux/perf_event.h linux-libre-3.8.13-gnu1/include/linux/perf_event.h
--- linux-libre-3.8-gnu1/include/linux/perf_event.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/perf_event.h	2013-05-11 16:57:46.000000000 -0400
@@ -794,6 +794,12 @@ static inline int __perf_event_disable(v
 static inline void perf_event_task_tick(void)				{ }
 #endif
 
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
+extern void perf_restore_debug_store(void);
+#else
+static inline void perf_restore_debug_store(void)			{ }
+#endif
+
 #define perf_output_put(handle, x) perf_output_copy((handle), &(x), sizeof(x))
 
 /*
diff -druNp linux-libre-3.8-gnu1/include/linux/pps_kernel.h linux-libre-3.8.13-gnu1/include/linux/pps_kernel.h
--- linux-libre-3.8-gnu1/include/linux/pps_kernel.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/pps_kernel.h	2013-05-11 16:57:46.000000000 -0400
@@ -43,7 +43,7 @@ struct pps_source_info {
 			int event, void *data);	/* PPS echo function */
 
 	struct module *owner;
-	struct device *dev;
+	struct device *dev;		/* Parent device for device_create */
 };
 
 struct pps_event_time {
@@ -69,6 +69,7 @@ struct pps_device {
 	wait_queue_head_t queue;		/* PPS event queue */
 
 	unsigned int id;			/* PPS source unique ID */
+	void const *lookup_cookie;		/* pps_lookup_dev only */
 	struct cdev cdev;
 	struct device *dev;
 	struct fasync_struct *async_queue;	/* fasync method */
@@ -82,16 +83,26 @@ struct pps_device {
 extern struct device_attribute pps_attrs[];
 
 /*
+ * Internal functions.
+ *
+ * These are not actually part of the exported API, but this is a
+ * convenient header file to put them in.
+ */
+
+extern int pps_register_cdev(struct pps_device *pps);
+extern void pps_unregister_cdev(struct pps_device *pps);
+
+/*
  * Exported functions
  */
 
 extern struct pps_device *pps_register_source(
 		struct pps_source_info *info, int default_params);
 extern void pps_unregister_source(struct pps_device *pps);
-extern int pps_register_cdev(struct pps_device *pps);
-extern void pps_unregister_cdev(struct pps_device *pps);
 extern void pps_event(struct pps_device *pps,
 		struct pps_event_time *ts, int event, void *data);
+/* Look up a pps device by magic cookie */
+struct pps_device *pps_lookup_dev(void const *cookie);
 
 static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
 		struct timespec ts)
diff -druNp linux-libre-3.8-gnu1/include/linux/preempt.h linux-libre-3.8.13-gnu1/include/linux/preempt.h
--- linux-libre-3.8-gnu1/include/linux/preempt.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/preempt.h	2013-05-11 16:57:46.000000000 -0400
@@ -93,14 +93,20 @@ do { \
 
 #else /* !CONFIG_PREEMPT_COUNT */
 
-#define preempt_disable()		do { } while (0)
-#define sched_preempt_enable_no_resched()	do { } while (0)
-#define preempt_enable_no_resched()	do { } while (0)
-#define preempt_enable()		do { } while (0)
+/*
+ * Even if we don't have any preemption, we need preempt disable/enable
+ * to be barriers, so that we don't have things like get_user/put_user
+ * that can cause faults and scheduling migrate into our preempt-protected
+ * region.
+ */
+#define preempt_disable()		barrier()
+#define sched_preempt_enable_no_resched()	barrier()
+#define preempt_enable_no_resched()	barrier()
+#define preempt_enable()		barrier()
 
-#define preempt_disable_notrace()		do { } while (0)
-#define preempt_enable_no_resched_notrace()	do { } while (0)
-#define preempt_enable_notrace()		do { } while (0)
+#define preempt_disable_notrace()		barrier()
+#define preempt_enable_no_resched_notrace()	barrier()
+#define preempt_enable_notrace()		barrier()
 
 #endif /* CONFIG_PREEMPT_COUNT */
 
diff -druNp linux-libre-3.8-gnu1/include/linux/pstore.h linux-libre-3.8.13-gnu1/include/linux/pstore.h
--- linux-libre-3.8-gnu1/include/linux/pstore.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/pstore.h	2013-05-11 16:57:46.000000000 -0400
@@ -68,12 +68,18 @@ struct pstore_info {
 
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
+extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
 #else
 static inline int
 pstore_register(struct pstore_info *psi)
 {
 	return -ENODEV;
 }
+static inline bool
+pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+	return false;
+}
 #endif
 
 #endif /*_LINUX_PSTORE_H*/
diff -druNp linux-libre-3.8-gnu1/include/linux/quota.h linux-libre-3.8.13-gnu1/include/linux/quota.h
--- linux-libre-3.8-gnu1/include/linux/quota.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/quota.h	2013-05-11 16:57:46.000000000 -0400
@@ -405,6 +405,7 @@ struct quota_module_name {
 #define INIT_QUOTA_MODULE_NAMES {\
 	{QFMT_VFS_OLD, "quota_v1"},\
 	{QFMT_VFS_V0, "quota_v2"},\
+	{QFMT_VFS_V1, "quota_v2"},\
 	{0, NULL}}
 
 #endif /* _QUOTA_ */
diff -druNp linux-libre-3.8-gnu1/include/linux/sched.h linux-libre-3.8.13-gnu1/include/linux/sched.h
--- linux-libre-3.8-gnu1/include/linux/sched.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/sched.h	2013-05-11 16:57:46.000000000 -0400
@@ -163,9 +163,10 @@ print_cfs_rq(struct seq_file *m, int cpu
 #define TASK_DEAD		64
 #define TASK_WAKEKILL		128
 #define TASK_WAKING		256
-#define TASK_STATE_MAX		512
+#define TASK_PARKED		512
+#define TASK_STATE_MAX		1024
 
-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW"
+#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
 
 extern char ___assert_task_state[1 - 2*!!(
 		sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)];
@@ -2485,27 +2486,18 @@ static inline void threadgroup_change_en
  *
  * Lock the threadgroup @tsk belongs to.  No new task is allowed to enter
  * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or
- * perform exec.  This is useful for cases where the threadgroup needs to
- * stay stable across blockable operations.
+ * change ->group_leader/pid.  This is useful for cases where the threadgroup
+ * needs to stay stable across blockable operations.
  *
  * fork and exit paths explicitly call threadgroup_change_{begin|end}() for
  * synchronization.  While held, no new task will be added to threadgroup
  * and no existing live task will have its PF_EXITING set.
  *
- * During exec, a task goes and puts its thread group through unusual
- * changes.  After de-threading, exclusive access is assumed to resources
- * which are usually shared by tasks in the same group - e.g. sighand may
- * be replaced with a new one.  Also, the exec'ing task takes over group
- * leader role including its pid.  Exclude these changes while locked by
- * grabbing cred_guard_mutex which is used to synchronize exec path.
+ * de_thread() does threadgroup_change_{begin|end}() when a non-leader
+ * sub-thread becomes a new leader.
  */
 static inline void threadgroup_lock(struct task_struct *tsk)
 {
-	/*
-	 * exec uses exit for de-threading nesting group_rwsem inside
-	 * cred_guard_mutex. Grab cred_guard_mutex first.
-	 */
-	mutex_lock(&tsk->signal->cred_guard_mutex);
 	down_write(&tsk->signal->group_rwsem);
 }
 
@@ -2518,7 +2510,6 @@ static inline void threadgroup_lock(stru
 static inline void threadgroup_unlock(struct task_struct *tsk)
 {
 	up_write(&tsk->signal->group_rwsem);
-	mutex_unlock(&tsk->signal->cred_guard_mutex);
 }
 #else
 static inline void threadgroup_change_begin(struct task_struct *tsk) {}
diff -druNp linux-libre-3.8-gnu1/include/linux/skbuff.h linux-libre-3.8.13-gnu1/include/linux/skbuff.h
--- linux-libre-3.8-gnu1/include/linux/skbuff.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/skbuff.h	2013-05-11 16:57:46.000000000 -0400
@@ -491,7 +491,7 @@ struct sk_buff {
 	union {
 		__u32		mark;
 		__u32		dropcount;
-		__u32		avail_size;
+		__u32		reserved_tailroom;
 	};
 
 	sk_buff_data_t		inner_transport_header;
@@ -1269,11 +1269,13 @@ static inline void __skb_fill_page_desc(
 	 * do not lose pfmemalloc information as the pages would not be
 	 * allocated using __GFP_MEMALLOC.
 	 */
-	if (page->pfmemalloc && !page->mapping)
-		skb->pfmemalloc	= true;
 	frag->page.p		  = page;
 	frag->page_offset	  = off;
 	skb_frag_size_set(frag, size);
+
+	page = compound_head(page);
+	if (page->pfmemalloc && !page->mapping)
+		skb->pfmemalloc	= true;
 }
 
 /**
@@ -1428,7 +1430,10 @@ static inline int skb_tailroom(const str
  */
 static inline int skb_availroom(const struct sk_buff *skb)
 {
-	return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len;
+	if (skb_is_nonlinear(skb))
+		return 0;
+
+	return skb->end - skb->tail - skb->reserved_tailroom;
 }
 
 /**
@@ -2592,6 +2597,13 @@ static inline void nf_reset(struct sk_bu
 #endif
 }
 
+static inline void nf_reset_trace(struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
+	skb->nf_trace = 0;
+#endif
+}
+
 /* Note: This doesn't put any conntrack and bridge info in dst. */
 static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 {
diff -druNp linux-libre-3.8-gnu1/include/linux/spinlock_up.h linux-libre-3.8.13-gnu1/include/linux/spinlock_up.h
--- linux-libre-3.8-gnu1/include/linux/spinlock_up.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/spinlock_up.h	2013-05-11 16:57:46.000000000 -0400
@@ -16,7 +16,10 @@
  * In the debug case, 1 means unlocked, 0 means locked. (the values
  * are inverted, to catch initialization bugs)
  *
- * No atomicity anywhere, we are on UP.
+ * No atomicity anywhere, we are on UP. However, we still need
+ * the compiler barriers, because we do not want the compiler to
+ * move potentially faulting instructions (notably user accesses)
+ * into the locked sequence, resulting in non-atomic execution.
  */
 
 #ifdef CONFIG_DEBUG_SPINLOCK
@@ -25,6 +28,7 @@
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
 	lock->slock = 0;
+	barrier();
 }
 
 static inline void
@@ -32,6 +36,7 @@ arch_spin_lock_flags(arch_spinlock_t *lo
 {
 	local_irq_save(flags);
 	lock->slock = 0;
+	barrier();
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *lock)
@@ -39,32 +44,34 @@ static inline int arch_spin_trylock(arch
 	char oldval = lock->slock;
 
 	lock->slock = 0;
+	barrier();
 
 	return oldval > 0;
 }
 
 static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
+	barrier();
 	lock->slock = 1;
 }
 
 /*
  * Read-write spinlocks. No debug version.
  */
-#define arch_read_lock(lock)		do { (void)(lock); } while (0)
-#define arch_write_lock(lock)		do { (void)(lock); } while (0)
-#define arch_read_trylock(lock)	({ (void)(lock); 1; })
-#define arch_write_trylock(lock)	({ (void)(lock); 1; })
-#define arch_read_unlock(lock)		do { (void)(lock); } while (0)
-#define arch_write_unlock(lock)	do { (void)(lock); } while (0)
+#define arch_read_lock(lock)		do { barrier(); (void)(lock); } while (0)
+#define arch_write_lock(lock)		do { barrier(); (void)(lock); } while (0)
+#define arch_read_trylock(lock)	({ barrier(); (void)(lock); 1; })
+#define arch_write_trylock(lock)	({ barrier(); (void)(lock); 1; })
+#define arch_read_unlock(lock)		do { barrier(); (void)(lock); } while (0)
+#define arch_write_unlock(lock)	do { barrier(); (void)(lock); } while (0)
 
 #else /* DEBUG_SPINLOCK */
 #define arch_spin_is_locked(lock)	((void)(lock), 0)
 /* for sched.c and kernel_lock.c: */
-# define arch_spin_lock(lock)		do { (void)(lock); } while (0)
-# define arch_spin_lock_flags(lock, flags)	do { (void)(lock); } while (0)
-# define arch_spin_unlock(lock)	do { (void)(lock); } while (0)
-# define arch_spin_trylock(lock)	({ (void)(lock); 1; })
+# define arch_spin_lock(lock)		do { barrier(); (void)(lock); } while (0)
+# define arch_spin_lock_flags(lock, flags)	do { barrier(); (void)(lock); } while (0)
+# define arch_spin_unlock(lock)	do { barrier(); (void)(lock); } while (0)
+# define arch_spin_trylock(lock)	({ barrier(); (void)(lock); 1; })
 #endif /* DEBUG_SPINLOCK */
 
 #define arch_spin_is_contended(lock)	(((void)(lock), 0))
diff -druNp linux-libre-3.8-gnu1/include/linux/ssb/ssb_driver_chipcommon.h linux-libre-3.8.13-gnu1/include/linux/ssb/ssb_driver_chipcommon.h
--- linux-libre-3.8-gnu1/include/linux/ssb/ssb_driver_chipcommon.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/ssb/ssb_driver_chipcommon.h	2013-05-11 16:57:46.000000000 -0400
@@ -219,6 +219,7 @@
 #define SSB_CHIPCO_PMU_CTL			0x0600 /* PMU control */
 #define  SSB_CHIPCO_PMU_CTL_ILP_DIV		0xFFFF0000 /* ILP div mask */
 #define  SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT	16
+#define  SSB_CHIPCO_PMU_CTL_PLL_UPD		0x00000400
 #define  SSB_CHIPCO_PMU_CTL_NOILPONW		0x00000200 /* No ILP on wait */
 #define  SSB_CHIPCO_PMU_CTL_HTREQEN		0x00000100 /* HT req enable */
 #define  SSB_CHIPCO_PMU_CTL_ALPREQEN		0x00000080 /* ALP req enable */
@@ -667,5 +668,6 @@ enum ssb_pmu_ldo_volt_id {
 void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
 			     enum ssb_pmu_ldo_volt_id id, u32 voltage);
 void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
+void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid);
 
 #endif /* LINUX_SSB_CHIPCO_H_ */
diff -druNp linux-libre-3.8-gnu1/include/linux/thermal.h linux-libre-3.8.13-gnu1/include/linux/thermal.h
--- linux-libre-3.8-gnu1/include/linux/thermal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/thermal.h	2013-05-11 16:57:46.000000000 -0400
@@ -44,7 +44,7 @@
 /* Adding event notification support elements */
 #define THERMAL_GENL_FAMILY_NAME                "thermal_event"
 #define THERMAL_GENL_VERSION                    0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_group"
+#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_grp"
 
 /* Default Thermal Governor */
 #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
diff -druNp linux-libre-3.8-gnu1/include/linux/usb/cdc_ncm.h linux-libre-3.8.13-gnu1/include/linux/usb/cdc_ncm.h
--- linux-libre-3.8-gnu1/include/linux/usb/cdc_ncm.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/usb/cdc_ncm.h	2013-05-11 16:57:46.000000000 -0400
@@ -127,6 +127,7 @@ struct cdc_ncm_ctx {
 	u16 connected;
 };
 
+extern u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf);
 extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
 extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
 extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);
diff -druNp linux-libre-3.8-gnu1/include/linux/usb/serial.h linux-libre-3.8.13-gnu1/include/linux/usb/serial.h
--- linux-libre-3.8-gnu1/include/linux/usb/serial.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/usb/serial.h	2013-05-11 16:57:46.000000000 -0400
@@ -66,6 +66,7 @@
  *	port.
  * @flags: usb serial port flags
  * @write_wait: a wait_queue_head_t used by the port.
+ * @delta_msr_wait: modem-status-change wait queue
  * @work: work queue entry for the line discipline waking up.
  * @throttled: nonzero if the read urb is inactive to throttle the device
  * @throttle_req: nonzero if the tty wants to throttle us
@@ -112,6 +113,7 @@ struct usb_serial_port {
 
 	unsigned long		flags;
 	wait_queue_head_t	write_wait;
+	wait_queue_head_t	delta_msr_wait;
 	struct work_struct	work;
 	char			throttled;
 	char			throttle_req;
diff -druNp linux-libre-3.8-gnu1/include/linux/user_namespace.h linux-libre-3.8.13-gnu1/include/linux/user_namespace.h
--- linux-libre-3.8-gnu1/include/linux/user_namespace.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/user_namespace.h	2013-05-11 16:57:46.000000000 -0400
@@ -26,6 +26,8 @@ struct user_namespace {
 	kuid_t			owner;
 	kgid_t			group;
 	unsigned int		proc_inum;
+	bool			may_mount_sysfs;
+	bool			may_mount_proc;
 };
 
 extern struct user_namespace init_user_ns;
@@ -82,4 +84,6 @@ static inline void put_user_ns(struct us
 
 #endif
 
+void update_mnt_policy(struct user_namespace *userns);
+
 #endif /* _LINUX_USER_H */
diff -druNp linux-libre-3.8-gnu1/include/linux/vt_kern.h linux-libre-3.8.13-gnu1/include/linux/vt_kern.h
--- linux-libre-3.8-gnu1/include/linux/vt_kern.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/linux/vt_kern.h	2013-05-11 16:57:46.000000000 -0400
@@ -47,6 +47,7 @@ int con_set_cmap(unsigned char __user *c
 int con_get_cmap(unsigned char __user *cmap);
 void scrollback(struct vc_data *vc, int lines);
 void scrollfront(struct vc_data *vc, int lines);
+void clear_buffer_attributes(struct vc_data *vc);
 void update_region(struct vc_data *vc, unsigned long start, int count);
 void redraw_screen(struct vc_data *vc, int is_switch);
 #define update_screen(x) redraw_screen(x, 0)
@@ -130,6 +131,8 @@ void vt_event_post(unsigned int event, u
 int vt_waitactive(int n);
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
+extern int do_unbind_con_driver(const struct consw *csw, int first, int last,
+			     int deflt);
 extern int unbind_con_driver(const struct consw *csw, int first, int last,
 			     int deflt);
 int vty_init(const struct file_operations *console_fops);
diff -druNp linux-libre-3.8-gnu1/include/net/dst.h linux-libre-3.8.13-gnu1/include/net/dst.h
--- linux-libre-3.8-gnu1/include/net/dst.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/dst.h	2013-05-11 16:57:46.000000000 -0400
@@ -36,13 +36,9 @@ struct dst_entry {
 	struct net_device       *dev;
 	struct  dst_ops	        *ops;
 	unsigned long		_metrics;
-	union {
-		unsigned long           expires;
-		/* point to where the dst_entry copied from */
-		struct dst_entry        *from;
-	};
+	unsigned long           expires;
 	struct dst_entry	*path;
-	void			*__pad0;
+	struct dst_entry	*from;
 #ifdef CONFIG_XFRM
 	struct xfrm_state	*xfrm;
 #else
diff -druNp linux-libre-3.8-gnu1/include/net/icmp.h linux-libre-3.8.13-gnu1/include/net/icmp.h
--- linux-libre-3.8-gnu1/include/net/icmp.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/icmp.h	2013-05-11 16:57:46.000000000 -0400
@@ -41,6 +41,7 @@ struct net;
 
 extern void	icmp_send(struct sk_buff *skb_in,  int type, int code, __be32 info);
 extern int	icmp_rcv(struct sk_buff *skb);
+extern void	icmp_err(struct sk_buff *, u32 info);
 extern int	icmp_init(void);
 extern void	icmp_out_count(struct net *net, unsigned char type);
 
diff -druNp linux-libre-3.8-gnu1/include/net/inet6_hashtables.h linux-libre-3.8.13-gnu1/include/net/inet6_hashtables.h
--- linux-libre-3.8-gnu1/include/net/inet6_hashtables.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/inet6_hashtables.h	2013-05-11 16:57:46.000000000 -0400
@@ -28,16 +28,16 @@
 
 struct inet_hashinfo;
 
-/* I have no idea if this is a good hash for v6 or not. -DaveM */
 static inline unsigned int inet6_ehashfn(struct net *net,
 				const struct in6_addr *laddr, const u16 lport,
 				const struct in6_addr *faddr, const __be16 fport)
 {
-	u32 ports = (lport ^ (__force u16)fport);
+	u32 ports = (((u32)lport) << 16) | (__force u32)fport;
 
 	return jhash_3words((__force u32)laddr->s6_addr32[3],
-			    (__force u32)faddr->s6_addr32[3],
-			    ports, inet_ehash_secret + net_hash_mix(net));
+			    ipv6_addr_jhash(faddr),
+			    ports,
+			    inet_ehash_secret + net_hash_mix(net));
 }
 
 static inline int inet6_sk_ehashfn(const struct sock *sk)
diff -druNp linux-libre-3.8-gnu1/include/net/inet_frag.h linux-libre-3.8.13-gnu1/include/net/inet_frag.h
--- linux-libre-3.8-gnu1/include/net/inet_frag.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/inet_frag.h	2013-05-11 16:57:46.000000000 -0400
@@ -35,6 +35,13 @@ struct inet_frag_queue {
 
 #define INETFRAGS_HASHSZ		64
 
+/* averaged:
+ * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
+ *	       rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
+ *	       struct frag_queue))
+ */
+#define INETFRAGS_MAXDEPTH		128
+
 struct inet_frags {
 	struct hlist_head	hash[INETFRAGS_HASHSZ];
 	rwlock_t		lock;
@@ -65,6 +72,8 @@ int inet_frag_evictor(struct netns_frags
 struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
 		struct inet_frags *f, void *key, unsigned int hash)
 	__releases(&f->lock);
+void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
+				   const char *prefix);
 
 static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
 {
diff -druNp linux-libre-3.8-gnu1/include/net/inet_sock.h linux-libre-3.8.13-gnu1/include/net/inet_sock.h
--- linux-libre-3.8-gnu1/include/net/inet_sock.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/inet_sock.h	2013-05-11 16:57:46.000000000 -0400
@@ -203,6 +203,7 @@ static inline void inet_sk_copy_descenda
 extern int inet_sk_rebuild_header(struct sock *sk);
 
 extern u32 inet_ehash_secret;
+extern u32 ipv6_hash_secret;
 extern void build_ehash_secret(void);
 
 static inline unsigned int inet_ehashfn(struct net *net,
diff -druNp linux-libre-3.8-gnu1/include/net/ip6_fib.h linux-libre-3.8.13-gnu1/include/net/ip6_fib.h
--- linux-libre-3.8-gnu1/include/net/ip6_fib.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/ip6_fib.h	2013-05-11 16:57:46.000000000 -0400
@@ -166,50 +166,35 @@ static inline struct inet6_dev *ip6_dst_
 
 static inline void rt6_clean_expires(struct rt6_info *rt)
 {
-	if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
-		dst_release(rt->dst.from);
-
 	rt->rt6i_flags &= ~RTF_EXPIRES;
-	rt->dst.from = NULL;
 }
 
 static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
 {
-	if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
-		dst_release(rt->dst.from);
-
-	rt->rt6i_flags |= RTF_EXPIRES;
 	rt->dst.expires = expires;
+	rt->rt6i_flags |= RTF_EXPIRES;
 }
 
-static inline void rt6_update_expires(struct rt6_info *rt, int timeout)
+static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
 {
-	if (!(rt->rt6i_flags & RTF_EXPIRES)) {
-		if (rt->dst.from)
-			dst_release(rt->dst.from);
-		/* dst_set_expires relies on expires == 0 
-		 * if it has not been set previously.
-		 */
-		rt->dst.expires = 0;
-	}
+	struct rt6_info *rt;
 
-	dst_set_expires(&rt->dst, timeout);
-	rt->rt6i_flags |= RTF_EXPIRES;
+	for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
+	     rt = (struct rt6_info *)rt->dst.from);
+	if (rt && rt != rt0)
+		rt0->dst.expires = rt->dst.expires;
+
+	dst_set_expires(&rt0->dst, timeout);
+	rt0->rt6i_flags |= RTF_EXPIRES;
 }
 
 static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
 {
 	struct dst_entry *new = (struct dst_entry *) from;
 
-	if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
-		if (new == rt->dst.from)
-			return;
-		dst_release(rt->dst.from);
-	}
-
 	rt->rt6i_flags &= ~RTF_EXPIRES;
-	rt->dst.from = new;
 	dst_hold(new);
+	rt->dst.from = new;
 }
 
 static inline void ip6_rt_put(struct rt6_info *rt)
diff -druNp linux-libre-3.8-gnu1/include/net/ip_fib.h linux-libre-3.8.13-gnu1/include/net/ip_fib.h
--- linux-libre-3.8-gnu1/include/net/ip_fib.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/ip_fib.h	2013-05-11 16:57:46.000000000 -0400
@@ -152,18 +152,16 @@ struct fib_result_nl {
 };
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-
 #define FIB_RES_NH(res)		((res).fi->fib_nh[(res).nh_sel])
-
-#define FIB_TABLE_HASHSZ 2
-
 #else /* CONFIG_IP_ROUTE_MULTIPATH */
-
 #define FIB_RES_NH(res)		((res).fi->fib_nh[0])
+#endif /* CONFIG_IP_ROUTE_MULTIPATH */
 
+#ifdef CONFIG_IP_MULTIPLE_TABLES
 #define FIB_TABLE_HASHSZ 256
-
-#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+#else
+#define FIB_TABLE_HASHSZ 2
+#endif
 
 extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
 
diff -druNp linux-libre-3.8-gnu1/include/net/ipv6.h linux-libre-3.8.13-gnu1/include/net/ipv6.h
--- linux-libre-3.8-gnu1/include/net/ipv6.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/ipv6.h	2013-05-11 16:57:46.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <linux/ipv6.h>
 #include <linux/hardirq.h>
+#include <linux/jhash.h>
 #include <net/if_inet6.h>
 #include <net/ndisc.h>
 #include <net/flow.h>
@@ -473,6 +474,17 @@ static inline u32 ipv6_addr_hash(const s
 #endif
 }
 
+/* more secured version of ipv6_addr_hash() */
+static inline u32 ipv6_addr_jhash(const struct in6_addr *a)
+{
+	u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1];
+
+	return jhash_3words(v,
+			    (__force u32)a->s6_addr32[2],
+			    (__force u32)a->s6_addr32[3],
+			    ipv6_hash_secret);
+}
+
 static inline bool ipv6_addr_loopback(const struct in6_addr *a)
 {
 	return (a->s6_addr32[0] | a->s6_addr32[1] |
diff -druNp linux-libre-3.8-gnu1/include/net/scm.h linux-libre-3.8.13-gnu1/include/net/scm.h
--- linux-libre-3.8-gnu1/include/net/scm.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/scm.h	2013-05-11 16:57:46.000000000 -0400
@@ -56,8 +56,8 @@ static __inline__ void scm_set_cred(stru
 	scm->pid  = get_pid(pid);
 	scm->cred = cred ? get_cred(cred) : NULL;
 	scm->creds.pid = pid_vnr(pid);
-	scm->creds.uid = cred ? cred->euid : INVALID_UID;
-	scm->creds.gid = cred ? cred->egid : INVALID_GID;
+	scm->creds.uid = cred ? cred->uid : INVALID_UID;
+	scm->creds.gid = cred ? cred->gid : INVALID_GID;
 }
 
 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
diff -druNp linux-libre-3.8-gnu1/include/net/sock.h linux-libre-3.8.13-gnu1/include/net/sock.h
--- linux-libre-3.8-gnu1/include/net/sock.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/net/sock.h	2013-05-11 16:57:46.000000000 -0400
@@ -1037,7 +1037,7 @@ static inline void sk_refcnt_debug_dec(s
 	       sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks));
 }
 
-inline void sk_refcnt_debug_release(const struct sock *sk)
+static inline void sk_refcnt_debug_release(const struct sock *sk)
 {
 	if (atomic_read(&sk->sk_refcnt) != 1)
 		printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
diff -druNp linux-libre-3.8-gnu1/include/sound/emu10k1.h linux-libre-3.8.13-gnu1/include/sound/emu10k1.h
--- linux-libre-3.8-gnu1/include/sound/emu10k1.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/sound/emu10k1.h	2013-05-11 16:57:46.000000000 -0400
@@ -1787,6 +1787,7 @@ struct snd_emu10k1 {
 	unsigned int next_free_voice;
 
 	const struct firmware *firmware;
+	const struct firmware *dock_fw;
 
 #ifdef CONFIG_PM_SLEEP
 	unsigned int *saved_ptr;
diff -druNp linux-libre-3.8-gnu1/include/trace/events/sched.h linux-libre-3.8.13-gnu1/include/trace/events/sched.h
--- linux-libre-3.8-gnu1/include/trace/events/sched.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/trace/events/sched.h	2013-05-11 16:57:46.000000000 -0400
@@ -147,7 +147,7 @@ TRACE_EVENT(sched_switch,
 		  __print_flags(__entry->prev_state & (TASK_STATE_MAX-1), "|",
 				{ 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" },
 				{ 16, "Z" }, { 32, "X" }, { 64, "x" },
-				{ 128, "W" }) : "R",
+				{ 128, "K" }, { 256, "W" }, { 512, "P" }) : "R",
 		__entry->prev_state & TASK_STATE_MAX ? "+" : "",
 		__entry->next_comm, __entry->next_pid, __entry->next_prio)
 );
diff -druNp linux-libre-3.8-gnu1/include/uapi/asm-generic/signal.h linux-libre-3.8.13-gnu1/include/uapi/asm-generic/signal.h
--- linux-libre-3.8-gnu1/include/uapi/asm-generic/signal.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/uapi/asm-generic/signal.h	2013-05-11 16:57:46.000000000 -0400
@@ -93,6 +93,10 @@ typedef unsigned long old_sigset_t;
 
 #include <asm-generic/signal-defs.h>
 
+#ifdef SA_RESTORER
+#define __ARCH_HAS_SA_RESTORER
+#endif
+
 struct sigaction {
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
diff -druNp linux-libre-3.8-gnu1/include/uapi/linux/packet_diag.h linux-libre-3.8.13-gnu1/include/uapi/linux/packet_diag.h
--- linux-libre-3.8-gnu1/include/uapi/linux/packet_diag.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/uapi/linux/packet_diag.h	2013-05-11 16:57:46.000000000 -0400
@@ -33,9 +33,11 @@ enum {
 	PACKET_DIAG_TX_RING,
 	PACKET_DIAG_FANOUT,
 
-	PACKET_DIAG_MAX,
+	__PACKET_DIAG_MAX,
 };
 
+#define PACKET_DIAG_MAX (__PACKET_DIAG_MAX - 1)
+
 struct packet_diag_info {
 	__u32	pdi_index;
 	__u32	pdi_version;
diff -druNp linux-libre-3.8-gnu1/include/uapi/linux/serial_core.h linux-libre-3.8.13-gnu1/include/uapi/linux/serial_core.h
--- linux-libre-3.8-gnu1/include/uapi/linux/serial_core.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/uapi/linux/serial_core.h	2013-05-11 16:57:46.000000000 -0400
@@ -50,8 +50,11 @@
 #define PORT_LPC3220	22	/* NXP LPC32xx SoC "Standard" UART */
 #define PORT_8250_CIR	23	/* CIR infrared port, has its own driver */
 #define PORT_XR17V35X	24	/* Exar XR17V35x UARTs */
-#define PORT_BRCM_TRUMANAGE	24
-#define PORT_MAX_8250	25	/* max port ID */
+#define PORT_BRCM_TRUMANAGE	25
+#define PORT_ALTR_16550_F32 26	/* Altera 16550 UART with 32 FIFOs */
+#define PORT_ALTR_16550_F64 27	/* Altera 16550 UART with 64 FIFOs */
+#define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
+#define PORT_MAX_8250	28	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
diff -druNp linux-libre-3.8-gnu1/include/uapi/linux/unix_diag.h linux-libre-3.8.13-gnu1/include/uapi/linux/unix_diag.h
--- linux-libre-3.8-gnu1/include/uapi/linux/unix_diag.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/uapi/linux/unix_diag.h	2013-05-11 16:57:46.000000000 -0400
@@ -39,9 +39,11 @@ enum {
 	UNIX_DIAG_MEMINFO,
 	UNIX_DIAG_SHUTDOWN,
 
-	UNIX_DIAG_MAX,
+	__UNIX_DIAG_MAX,
 };
 
+#define UNIX_DIAG_MAX (__UNIX_DIAG_MAX - 1)
+
 struct unix_diag_vfs {
 	__u32	udiag_vfs_ino;
 	__u32	udiag_vfs_dev;
diff -druNp linux-libre-3.8-gnu1/include/uapi/linux/usb/audio.h linux-libre-3.8.13-gnu1/include/uapi/linux/usb/audio.h
--- linux-libre-3.8-gnu1/include/uapi/linux/usb/audio.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/uapi/linux/usb/audio.h	2013-05-11 16:57:46.000000000 -0400
@@ -384,14 +384,16 @@ static inline __u8 uac_processing_unit_i
 						   int protocol)
 {
 	__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-	return desc->baSourceID[desc->bNrInPins + control_size];
+	return *(uac_processing_unit_bmControls(desc, protocol)
+			+ control_size);
 }
 
 static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
 						 int protocol)
 {
 	__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-	return &desc->baSourceID[desc->bNrInPins + control_size + 1];
+	return uac_processing_unit_bmControls(desc, protocol)
+			+ control_size + 1;
 }
 
 /* 4.5.2 Class-Specific AS Interface Descriptor */
diff -druNp linux-libre-3.8-gnu1/include/video/atmel_lcdc.h linux-libre-3.8.13-gnu1/include/video/atmel_lcdc.h
--- linux-libre-3.8-gnu1/include/video/atmel_lcdc.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/video/atmel_lcdc.h	2013-05-11 16:57:46.000000000 -0400
@@ -62,6 +62,7 @@ struct atmel_lcdfb_info {
 	void (*atmel_lcdfb_power_control)(int on);
 	struct fb_monspecs	*default_monspecs;
 	u32			pseudo_palette[16];
+	bool			have_intensity_bit;
 };
 
 #define ATMEL_LCDC_DMABADDR1	0x00
diff -druNp linux-libre-3.8-gnu1/include/xen/interface/io/blkif.h linux-libre-3.8.13-gnu1/include/xen/interface/io/blkif.h
--- linux-libre-3.8-gnu1/include/xen/interface/io/blkif.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/xen/interface/io/blkif.h	2013-05-11 16:57:46.000000000 -0400
@@ -138,11 +138,21 @@ struct blkif_request_discard {
 	uint8_t        _pad3;
 } __attribute__((__packed__));
 
+struct blkif_request_other {
+	uint8_t      _pad1;
+	blkif_vdev_t _pad2;        /* only for read/write requests         */
+#ifdef CONFIG_X86_64
+	uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
+#endif
+	uint64_t     id;           /* private guest value, echoed in resp  */
+} __attribute__((__packed__));
+
 struct blkif_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	union {
 		struct blkif_request_rw rw;
 		struct blkif_request_discard discard;
+		struct blkif_request_other other;
 	} u;
 } __attribute__((__packed__));
 
diff -druNp linux-libre-3.8-gnu1/include/xen/interface/physdev.h linux-libre-3.8.13-gnu1/include/xen/interface/physdev.h
--- linux-libre-3.8-gnu1/include/xen/interface/physdev.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/include/xen/interface/physdev.h	2013-05-11 16:57:46.000000000 -0400
@@ -251,6 +251,12 @@ struct physdev_pci_device_add {
 
 #define PHYSDEVOP_pci_device_remove     26
 #define PHYSDEVOP_restore_msi_ext       27
+/*
+ * Dom0 should use these two to announce MMIO resources assigned to
+ * MSI-X capable devices won't (prepare) or may (release) change.
+ */
+#define PHYSDEVOP_prepare_msix          30
+#define PHYSDEVOP_release_msix          31
 struct physdev_pci_device {
     /* IN */
     uint16_t seg;
diff -druNp linux-libre-3.8-gnu1/ipc/mqueue.c linux-libre-3.8.13-gnu1/ipc/mqueue.c
--- linux-libre-3.8-gnu1/ipc/mqueue.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/ipc/mqueue.c	2013-05-11 16:57:46.000000000 -0400
@@ -330,8 +330,16 @@ static struct dentry *mqueue_mount(struc
 			 int flags, const char *dev_name,
 			 void *data)
 {
-	if (!(flags & MS_KERNMOUNT))
-		data = current->nsproxy->ipc_ns;
+	if (!(flags & MS_KERNMOUNT)) {
+		struct ipc_namespace *ns = current->nsproxy->ipc_ns;
+		/* Don't allow mounting unless the caller has CAP_SYS_ADMIN
+		 * over the ipc namespace.
+		 */
+		if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+			return ERR_PTR(-EPERM);
+
+		data = ns;
+	}
 	return mount_ns(fs_type, flags, data, mqueue_fill_super);
 }
 
@@ -840,7 +848,8 @@ out_putfd:
 		fd = error;
 	}
 	mutex_unlock(&root->d_inode->i_mutex);
-	mnt_drop_write(mnt);
+	if (!ro)
+		mnt_drop_write(mnt);
 out_putname:
 	putname(name);
 	return fd;
diff -druNp linux-libre-3.8-gnu1/ipc/msg.c linux-libre-3.8.13-gnu1/ipc/msg.c
--- linux-libre-3.8-gnu1/ipc/msg.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/ipc/msg.c	2013-05-11 16:57:46.000000000 -0400
@@ -820,15 +820,17 @@ long do_msgrcv(int msqid, void __user *b
 	struct msg_msg *copy = NULL;
 	unsigned long copy_number = 0;
 
+	ns = current->nsproxy->ipc_ns;
+
 	if (msqid < 0 || (long) bufsz < 0)
 		return -EINVAL;
 	if (msgflg & MSG_COPY) {
-		copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, &copy_number);
+		copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax),
+				    msgflg, &msgtyp, &copy_number);
 		if (IS_ERR(copy))
 			return PTR_ERR(copy);
 	}
 	mode = convert_mode(&msgtyp, msgflg);
-	ns = current->nsproxy->ipc_ns;
 
 	msq = msg_lock_check(ns, msqid);
 	if (IS_ERR(msq)) {
@@ -870,6 +872,7 @@ long do_msgrcv(int msqid, void __user *b
 							goto out_unlock;
 						break;
 					}
+					msg = ERR_PTR(-EAGAIN);
 				} else
 					break;
 				msg_counter++;
diff -druNp linux-libre-3.8-gnu1/ipc/msgutil.c linux-libre-3.8.13-gnu1/ipc/msgutil.c
--- linux-libre-3.8-gnu1/ipc/msgutil.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/ipc/msgutil.c	2013-05-11 16:57:46.000000000 -0400
@@ -117,9 +117,6 @@ struct msg_msg *copy_msg(struct msg_msg
 	if (alen > DATALEN_MSG)
 		alen = DATALEN_MSG;
 
-	dst->next = NULL;
-	dst->security = NULL;
-
 	memcpy(dst + 1, src + 1, alen);
 
 	len -= alen;
diff -druNp linux-libre-3.8-gnu1/ipc/shm.c linux-libre-3.8.13-gnu1/ipc/shm.c
--- linux-libre-3.8-gnu1/ipc/shm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/ipc/shm.c	2013-05-11 16:57:46.000000000 -0400
@@ -462,7 +462,7 @@ static int newseg(struct ipc_namespace *
 	size_t size = params->u.size;
 	int error;
 	struct shmid_kernel *shp;
-	int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
+	size_t numpages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	struct file * file;
 	char name[13];
 	int id;
@@ -491,10 +491,14 @@ static int newseg(struct ipc_namespace *
 
 	sprintf (name, "SYSV%08x", key);
 	if (shmflg & SHM_HUGETLB) {
+		struct hstate *hs = hstate_sizelog((shmflg >> SHM_HUGE_SHIFT)
+						& SHM_HUGE_MASK);
+		size_t hugesize = ALIGN(size, huge_page_size(hs));
+
 		/* hugetlb_file_setup applies strict accounting */
 		if (shmflg & SHM_NORESERVE)
 			acctflag = VM_NORESERVE;
-		file = hugetlb_file_setup(name, 0, size, acctflag,
+		file = hugetlb_file_setup(name, hugesize, acctflag,
 				  &shp->mlock_user, HUGETLB_SHMFS_INODE,
 				(shmflg >> SHM_HUGE_SHIFT) & SHM_HUGE_MASK);
 	} else {
diff -druNp linux-libre-3.8-gnu1/kernel/audit_tree.c linux-libre-3.8.13-gnu1/kernel/audit_tree.c
--- linux-libre-3.8-gnu1/kernel/audit_tree.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/audit_tree.c	2013-05-11 16:57:46.000000000 -0400
@@ -617,9 +617,9 @@ void audit_trim_trees(void)
 		}
 		spin_unlock(&hash_lock);
 		trim_marked(tree);
-		put_tree(tree);
 		drop_collected_mounts(root_mnt);
 skip_it:
+		put_tree(tree);
 		mutex_lock(&audit_filter_mutex);
 	}
 	list_del(&cursor);
diff -druNp linux-libre-3.8-gnu1/kernel/capability.c linux-libre-3.8.13-gnu1/kernel/capability.c
--- linux-libre-3.8-gnu1/kernel/capability.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/capability.c	2013-05-11 16:57:46.000000000 -0400
@@ -393,6 +393,30 @@ bool ns_capable(struct user_namespace *n
 EXPORT_SYMBOL(ns_capable);
 
 /**
+ * file_ns_capable - Determine if the file's opener had a capability in effect
+ * @file:  The file we want to check
+ * @ns:  The usernamespace we want the capability in
+ * @cap: The capability to be tested for
+ *
+ * Return true if task that opened the file had a capability in effect
+ * when the file was opened.
+ *
+ * This does not set PF_SUPERPRIV because the caller may not
+ * actually be privileged.
+ */
+bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap)
+{
+	if (WARN_ON_ONCE(!cap_valid(cap)))
+		return false;
+
+	if (security_capable(file->f_cred, ns, cap) == 0)
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL(file_ns_capable);
+
+/**
  * capable - Determine if the current task has a superior capability in effect
  * @cap: The capability to be tested for
  *
diff -druNp linux-libre-3.8-gnu1/kernel/cgroup.c linux-libre-3.8.13-gnu1/kernel/cgroup.c
--- linux-libre-3.8-gnu1/kernel/cgroup.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/cgroup.c	2013-05-11 16:57:46.000000000 -0400
@@ -162,6 +162,9 @@ struct cfent {
 	struct list_head		node;
 	struct dentry			*dentry;
 	struct cftype			*type;
+
+	/* file xattrs */
+	struct simple_xattrs		xattrs;
 };
 
 /*
@@ -426,12 +429,20 @@ static void __put_css_set(struct css_set
 		struct cgroup *cgrp = link->cgrp;
 		list_del(&link->cg_link_list);
 		list_del(&link->cgrp_link_list);
+
+		/*
+		 * We may not be holding cgroup_mutex, and if cgrp->count is
+		 * dropped to 0 the cgroup can be destroyed at any time, hence
+		 * rcu_read_lock is used to keep it alive.
+		 */
+		rcu_read_lock();
 		if (atomic_dec_and_test(&cgrp->count) &&
 		    notify_on_release(cgrp)) {
 			if (taskexit)
 				set_bit(CGRP_RELEASABLE, &cgrp->flags);
 			check_for_release(cgrp);
 		}
+		rcu_read_unlock();
 
 		kfree(link);
 	}
@@ -900,13 +911,12 @@ static void cgroup_diput(struct dentry *
 	} else {
 		struct cfent *cfe = __d_cfe(dentry);
 		struct cgroup *cgrp = dentry->d_parent->d_fsdata;
-		struct cftype *cft = cfe->type;
 
 		WARN_ONCE(!list_empty(&cfe->node) &&
 			  cgrp != &cgrp->root->top_cgroup,
 			  "cfe still linked for %s\n", cfe->type->name);
+		simple_xattrs_free(&cfe->xattrs);
 		kfree(cfe);
-		simple_xattrs_free(&cft->xattrs);
 	}
 	iput(inode);
 }
@@ -2058,7 +2068,7 @@ static int cgroup_attach_proc(struct cgr
 	if (!group)
 		return -ENOMEM;
 	/* pre-allocate to guarantee space while iterating in rcu read-side. */
-	retval = flex_array_prealloc(group, 0, group_size - 1, GFP_KERNEL);
+	retval = flex_array_prealloc(group, 0, group_size, GFP_KERNEL);
 	if (retval)
 		goto out_free_group_list;
 
@@ -2545,7 +2555,7 @@ static struct simple_xattrs *__d_xattrs(
 	if (S_ISDIR(dentry->d_inode->i_mode))
 		return &__d_cgrp(dentry)->xattrs;
 	else
-		return &__d_cft(dentry)->xattrs;
+		return &__d_cfe(dentry)->xattrs;
 }
 
 static inline int xattr_enabled(struct dentry *dentry)
@@ -2721,8 +2731,6 @@ static int cgroup_add_file(struct cgroup
 	umode_t mode;
 	char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
 
-	simple_xattrs_init(&cft->xattrs);
-
 	if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
 		strcpy(name, subsys->name);
 		strcat(name, ".");
@@ -2747,6 +2755,7 @@ static int cgroup_add_file(struct cgroup
 		cfe->type = (void *)cft;
 		cfe->dentry = dentry;
 		dentry->d_fsdata = cfe;
+		simple_xattrs_init(&cfe->xattrs);
 		list_add_tail(&cfe->node, &parent->files);
 		cfe = NULL;
 	}
diff -druNp linux-libre-3.8-gnu1/kernel/cpuset.c linux-libre-3.8.13-gnu1/kernel/cpuset.c
--- linux-libre-3.8-gnu1/kernel/cpuset.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/cpuset.c	2013-05-11 16:57:46.000000000 -0400
@@ -2511,8 +2511,16 @@ void cpuset_print_task_mems_allowed(stru
 
 	dentry = task_cs(tsk)->css.cgroup->dentry;
 	spin_lock(&cpuset_buffer_lock);
-	snprintf(cpuset_name, CPUSET_NAME_LEN,
-		 dentry ? (const char *)dentry->d_name.name : "/");
+
+	if (!dentry) {
+		strcpy(cpuset_name, "/");
+	} else {
+		spin_lock(&dentry->d_lock);
+		strlcpy(cpuset_name, (const char *)dentry->d_name.name,
+			CPUSET_NAME_LEN);
+		spin_unlock(&dentry->d_lock);
+	}
+
 	nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
 			   tsk->mems_allowed);
 	printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n",
diff -druNp linux-libre-3.8-gnu1/kernel/events/core.c linux-libre-3.8.13-gnu1/kernel/events/core.c
--- linux-libre-3.8-gnu1/kernel/events/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/events/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -5328,7 +5328,7 @@ static void sw_perf_event_destroy(struct
 
 static int perf_swevent_init(struct perf_event *event)
 {
-	int event_id = event->attr.config;
+	u64 event_id = event->attr.config;
 
 	if (event->attr.type != PERF_TYPE_SOFTWARE)
 		return -ENOENT;
diff -druNp linux-libre-3.8-gnu1/kernel/fork.c linux-libre-3.8.13-gnu1/kernel/fork.c
--- linux-libre-3.8-gnu1/kernel/fork.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/fork.c	2013-05-11 16:57:46.000000000 -0400
@@ -1141,6 +1141,9 @@ static struct task_struct *copy_process(
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 		return ERR_PTR(-EINVAL);
 
+	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
+		return ERR_PTR(-EINVAL);
+
 	/*
 	 * Thread groups must share signals as well, and detached threads
 	 * can only be started up within the thread group.
@@ -1801,7 +1804,7 @@ SYSCALL_DEFINE1(unshare, unsigned long,
 	 * If unsharing a user namespace must also unshare the thread.
 	 */
 	if (unshare_flags & CLONE_NEWUSER)
-		unshare_flags |= CLONE_THREAD;
+		unshare_flags |= CLONE_THREAD | CLONE_FS;
 	/*
 	 * If unsharing a pid namespace must also unshare the thread.
 	 */
diff -druNp linux-libre-3.8-gnu1/kernel/futex.c linux-libre-3.8.13-gnu1/kernel/futex.c
--- linux-libre-3.8-gnu1/kernel/futex.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/futex.c	2013-05-11 16:57:46.000000000 -0400
@@ -2471,8 +2471,6 @@ SYSCALL_DEFINE3(get_robust_list, int, pi
 	if (!futex_cmpxchg_enabled)
 		return -ENOSYS;
 
-	WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n");
-
 	rcu_read_lock();
 
 	ret = -ESRCH;
diff -druNp linux-libre-3.8-gnu1/kernel/futex_compat.c linux-libre-3.8.13-gnu1/kernel/futex_compat.c
--- linux-libre-3.8-gnu1/kernel/futex_compat.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/futex_compat.c	2013-05-11 16:57:46.000000000 -0400
@@ -142,8 +142,6 @@ compat_sys_get_robust_list(int pid, comp
 	if (!futex_cmpxchg_enabled)
 		return -ENOSYS;
 
-	WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n");
-
 	rcu_read_lock();
 
 	ret = -ESRCH;
diff -druNp linux-libre-3.8-gnu1/kernel/hrtimer.c linux-libre-3.8.13-gnu1/kernel/hrtimer.c
--- linux-libre-3.8-gnu1/kernel/hrtimer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/hrtimer.c	2013-05-11 16:57:46.000000000 -0400
@@ -61,6 +61,7 @@
 DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
 
+	.lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
 	.clock_base =
 	{
 		{
@@ -297,6 +298,10 @@ ktime_t ktime_sub_ns(const ktime_t kt, u
 	} else {
 		unsigned long rem = do_div(nsec, NSEC_PER_SEC);
 
+		/* Make sure nsec fits into long */
+		if (unlikely(nsec > KTIME_SEC_MAX))
+			return (ktime_t){ .tv64 = KTIME_MAX };
+
 		tmp = ktime_set((long)nsec, rem);
 	}
 
@@ -640,21 +645,9 @@ static inline void hrtimer_init_hres(str
  * and expiry check is done in the hrtimer_interrupt or in the softirq.
  */
 static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
-					    struct hrtimer_clock_base *base,
-					    int wakeup)
+					    struct hrtimer_clock_base *base)
 {
-	if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
-		if (wakeup) {
-			raw_spin_unlock(&base->cpu_base->lock);
-			raise_softirq_irqoff(HRTIMER_SOFTIRQ);
-			raw_spin_lock(&base->cpu_base->lock);
-		} else
-			__raise_softirq_irqoff(HRTIMER_SOFTIRQ);
-
-		return 1;
-	}
-
-	return 0;
+	return base->cpu_base->hres_active && hrtimer_reprogram(timer, base);
 }
 
 static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
@@ -735,8 +728,7 @@ static inline int hrtimer_switch_to_hres
 static inline void
 hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
 static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
-					    struct hrtimer_clock_base *base,
-					    int wakeup)
+					    struct hrtimer_clock_base *base)
 {
 	return 0;
 }
@@ -995,8 +987,21 @@ int __hrtimer_start_range_ns(struct hrti
 	 *
 	 * XXX send_remote_softirq() ?
 	 */
-	if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
-		hrtimer_enqueue_reprogram(timer, new_base, wakeup);
+	if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)
+		&& hrtimer_enqueue_reprogram(timer, new_base)) {
+		if (wakeup) {
+			/*
+			 * We need to drop cpu_base->lock to avoid a
+			 * lock ordering issue vs. rq->lock.
+			 */
+			raw_spin_unlock(&new_base->cpu_base->lock);
+			raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+			local_irq_restore(flags);
+			return ret;
+		} else {
+			__raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+		}
+	}
 
 	unlock_hrtimer_base(timer, &flags);
 
@@ -1307,6 +1312,8 @@ retry:
 
 				expires = ktime_sub(hrtimer_get_expires(timer),
 						    base->offset);
+				if (expires.tv64 < 0)
+					expires.tv64 = KTIME_MAX;
 				if (expires.tv64 < expires_next.tv64)
 					expires_next = expires;
 				break;
@@ -1640,8 +1647,6 @@ static void __cpuinit init_hrtimers_cpu(
 	struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
 	int i;
 
-	raw_spin_lock_init(&cpu_base->lock);
-
 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
 		cpu_base->clock_base[i].cpu_base = cpu_base;
 		timerqueue_init_head(&cpu_base->clock_base[i].active);
diff -druNp linux-libre-3.8-gnu1/kernel/irq/spurious.c linux-libre-3.8.13-gnu1/kernel/irq/spurious.c
--- linux-libre-3.8-gnu1/kernel/irq/spurious.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/irq/spurious.c	2013-05-11 16:57:46.000000000 -0400
@@ -80,13 +80,11 @@ static int try_one_irq(int irq, struct i
 
 	/*
 	 * All handlers must agree on IRQF_SHARED, so we test just the
-	 * first. Check for action->next as well.
+	 * first.
 	 */
 	action = desc->action;
 	if (!action || !(action->flags & IRQF_SHARED) ||
-	    (action->flags & __IRQF_TIMER) ||
-	    (action->handler(irq, action->dev_id) == IRQ_HANDLED) ||
-	    !action->next)
+	    (action->flags & __IRQF_TIMER))
 		goto out;
 
 	/* Already running on another processor */
@@ -104,6 +102,7 @@ static int try_one_irq(int irq, struct i
 	do {
 		if (handle_irq_event(desc) == IRQ_HANDLED)
 			ret = IRQ_HANDLED;
+		/* Make sure that there is still a valid action */
 		action = desc->action;
 	} while ((desc->istate & IRQS_PENDING) && action);
 	desc->istate &= ~IRQS_POLL_INPROGRESS;
diff -druNp linux-libre-3.8-gnu1/kernel/kthread.c linux-libre-3.8.13-gnu1/kernel/kthread.c
--- linux-libre-3.8-gnu1/kernel/kthread.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/kthread.c	2013-05-11 16:57:46.000000000 -0400
@@ -124,12 +124,12 @@ void *kthread_data(struct task_struct *t
 
 static void __kthread_parkme(struct kthread *self)
 {
-	__set_current_state(TASK_INTERRUPTIBLE);
+	__set_current_state(TASK_PARKED);
 	while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) {
 		if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags))
 			complete(&self->parked);
 		schedule();
-		__set_current_state(TASK_INTERRUPTIBLE);
+		__set_current_state(TASK_PARKED);
 	}
 	clear_bit(KTHREAD_IS_PARKED, &self->flags);
 	__set_current_state(TASK_RUNNING);
@@ -256,8 +256,13 @@ struct task_struct *kthread_create_on_no
 }
 EXPORT_SYMBOL(kthread_create_on_node);
 
-static void __kthread_bind(struct task_struct *p, unsigned int cpu)
+static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state)
 {
+	/* Must have done schedule() in kthread() before we set_task_cpu */
+	if (!wait_task_inactive(p, state)) {
+		WARN_ON(1);
+		return;
+	}
 	/* It's safe because the task is inactive. */
 	do_set_cpus_allowed(p, cpumask_of(cpu));
 	p->flags |= PF_THREAD_BOUND;
@@ -274,12 +279,7 @@ static void __kthread_bind(struct task_s
  */
 void kthread_bind(struct task_struct *p, unsigned int cpu)
 {
-	/* Must have done schedule() in kthread() before we set_task_cpu */
-	if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) {
-		WARN_ON(1);
-		return;
-	}
-	__kthread_bind(p, cpu);
+	__kthread_bind(p, cpu, TASK_UNINTERRUPTIBLE);
 }
 EXPORT_SYMBOL(kthread_bind);
 
@@ -324,6 +324,22 @@ static struct kthread *task_get_live_kth
 	return NULL;
 }
 
+static void __kthread_unpark(struct task_struct *k, struct kthread *kthread)
+{
+	clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+	/*
+	 * We clear the IS_PARKED bit here as we don't wait
+	 * until the task has left the park code. So if we'd
+	 * park before that happens we'd see the IS_PARKED bit
+	 * which might be about to be cleared.
+	 */
+	if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
+		if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
+			__kthread_bind(k, kthread->cpu, TASK_PARKED);
+		wake_up_state(k, TASK_PARKED);
+	}
+}
+
 /**
  * kthread_unpark - unpark a thread created by kthread_create().
  * @k:		thread created by kthread_create().
@@ -336,20 +352,8 @@ void kthread_unpark(struct task_struct *
 {
 	struct kthread *kthread = task_get_live_kthread(k);
 
-	if (kthread) {
-		clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
-		/*
-		 * We clear the IS_PARKED bit here as we don't wait
-		 * until the task has left the park code. So if we'd
-		 * park before that happens we'd see the IS_PARKED bit
-		 * which might be about to be cleared.
-		 */
-		if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
-			if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
-				__kthread_bind(k, kthread->cpu);
-			wake_up_process(k);
-		}
-	}
+	if (kthread)
+		__kthread_unpark(k, kthread);
 	put_task_struct(k);
 }
 
@@ -407,7 +411,7 @@ int kthread_stop(struct task_struct *k)
 	trace_sched_kthread_stop(k);
 	if (kthread) {
 		set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
-		clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+		__kthread_unpark(k, kthread);
 		wake_up_process(k);
 		wait_for_completion(&kthread->exited);
 	}
diff -druNp linux-libre-3.8-gnu1/kernel/pid_namespace.c linux-libre-3.8.13-gnu1/kernel/pid_namespace.c
--- linux-libre-3.8-gnu1/kernel/pid_namespace.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/pid_namespace.c	2013-05-11 16:57:46.000000000 -0400
@@ -181,6 +181,7 @@ void zap_pid_ns_processes(struct pid_nam
 	int nr;
 	int rc;
 	struct task_struct *task, *me = current;
+	int init_pids = thread_group_leader(me) ? 1 : 2;
 
 	/* Don't allow any more processes into the pid namespace */
 	disable_pid_allocation(pid_ns);
@@ -230,7 +231,7 @@ void zap_pid_ns_processes(struct pid_nam
 	 */
 	for (;;) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (pid_ns->nr_hashed == 1)
+		if (pid_ns->nr_hashed == init_pids)
 			break;
 		schedule();
 	}
diff -druNp linux-libre-3.8-gnu1/kernel/posix-cpu-timers.c linux-libre-3.8.13-gnu1/kernel/posix-cpu-timers.c
--- linux-libre-3.8-gnu1/kernel/posix-cpu-timers.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/posix-cpu-timers.c	2013-05-11 16:57:46.000000000 -0400
@@ -1401,8 +1401,10 @@ static int do_cpu_nanosleep(const clocki
 		while (!signal_pending(current)) {
 			if (timer.it.cpu.expires.sched == 0) {
 				/*
-				 * Our timer fired and was reset.
+				 * Our timer fired and was reset, below
+				 * deletion can not fail.
 				 */
+				posix_cpu_timer_del(&timer);
 				spin_unlock_irq(&timer.it_lock);
 				return 0;
 			}
@@ -1420,9 +1422,26 @@ static int do_cpu_nanosleep(const clocki
 		 * We were interrupted by a signal.
 		 */
 		sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
-		posix_cpu_timer_set(&timer, 0, &zero_it, it);
+		error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+		if (!error) {
+			/*
+			 * Timer is now unarmed, deletion can not fail.
+			 */
+			posix_cpu_timer_del(&timer);
+		}
 		spin_unlock_irq(&timer.it_lock);
 
+		while (error == TIMER_RETRY) {
+			/*
+			 * We need to handle case when timer was or is in the
+			 * middle of firing. In other cases we already freed
+			 * resources.
+			 */
+			spin_lock_irq(&timer.it_lock);
+			error = posix_cpu_timer_del(&timer);
+			spin_unlock_irq(&timer.it_lock);
+		}
+
 		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
 			/*
 			 * It actually did fire already.
diff -druNp linux-libre-3.8-gnu1/kernel/posix-timers.c linux-libre-3.8.13-gnu1/kernel/posix-timers.c
--- linux-libre-3.8-gnu1/kernel/posix-timers.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/posix-timers.c	2013-05-11 16:57:46.000000000 -0400
@@ -639,6 +639,13 @@ static struct k_itimer *__lock_timer(tim
 {
 	struct k_itimer *timr;
 
+	/*
+	 * timer_t could be any type >= int and we want to make sure any
+	 * @timer_id outside positive int range fails lookup.
+	 */
+	if ((unsigned long long)timer_id > INT_MAX)
+		return NULL;
+
 	rcu_read_lock();
 	timr = idr_find(&posix_timers_id, (int)timer_id);
 	if (timr) {
diff -druNp linux-libre-3.8-gnu1/kernel/rcutree_trace.c linux-libre-3.8.13-gnu1/kernel/rcutree_trace.c
--- linux-libre-3.8-gnu1/kernel/rcutree_trace.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/rcutree_trace.c	2013-05-11 16:57:46.000000000 -0400
@@ -97,7 +97,7 @@ static const struct file_operations rcub
 	.open = rcubarrier_open,
 	.read = seq_read,
 	.llseek = no_llseek,
-	.release = seq_release,
+	.release = single_release,
 };
 
 #ifdef CONFIG_RCU_BOOST
@@ -208,7 +208,7 @@ static const struct file_operations rcue
 	.open = rcuexp_open,
 	.read = seq_read,
 	.llseek = no_llseek,
-	.release = seq_release,
+	.release = single_release,
 };
 
 #ifdef CONFIG_RCU_BOOST
@@ -308,7 +308,7 @@ static const struct file_operations rcuh
 	.open = rcuhier_open,
 	.read = seq_read,
 	.llseek = no_llseek,
-	.release = seq_release,
+	.release = single_release,
 };
 
 static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
@@ -350,7 +350,7 @@ static const struct file_operations rcug
 	.open = rcugp_open,
 	.read = seq_read,
 	.llseek = no_llseek,
-	.release = seq_release,
+	.release = single_release,
 };
 
 static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
diff -druNp linux-libre-3.8-gnu1/kernel/sched/clock.c linux-libre-3.8.13-gnu1/kernel/sched/clock.c
--- linux-libre-3.8-gnu1/kernel/sched/clock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/sched/clock.c	2013-05-11 16:57:46.000000000 -0400
@@ -176,10 +176,36 @@ static u64 sched_clock_remote(struct sch
 	u64 this_clock, remote_clock;
 	u64 *ptr, old_val, val;
 
+#if BITS_PER_LONG != 64
+again:
+	/*
+	 * Careful here: The local and the remote clock values need to
+	 * be read out atomic as we need to compare the values and
+	 * then update either the local or the remote side. So the
+	 * cmpxchg64 below only protects one readout.
+	 *
+	 * We must reread via sched_clock_local() in the retry case on
+	 * 32bit as an NMI could use sched_clock_local() via the
+	 * tracer and hit between the readout of
+	 * the low32bit and the high 32bit portion.
+	 */
+	this_clock = sched_clock_local(my_scd);
+	/*
+	 * We must enforce atomic readout on 32bit, otherwise the
+	 * update on the remote cpu can hit inbetween the readout of
+	 * the low32bit and the high 32bit portion.
+	 */
+	remote_clock = cmpxchg64(&scd->clock, 0, 0);
+#else
+	/*
+	 * On 64bit the read of [my]scd->clock is atomic versus the
+	 * update, so we can avoid the above 32bit dance.
+	 */
 	sched_clock_local(my_scd);
 again:
 	this_clock = my_scd->clock;
 	remote_clock = scd->clock;
+#endif
 
 	/*
 	 * Use the opportunity that we have both locks
diff -druNp linux-libre-3.8-gnu1/kernel/sched/core.c linux-libre-3.8.13-gnu1/kernel/sched/core.c
--- linux-libre-3.8-gnu1/kernel/sched/core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/sched/core.c	2013-05-11 16:57:46.000000000 -0400
@@ -1488,8 +1488,10 @@ static void try_to_wake_up_local(struct
 {
 	struct rq *rq = task_rq(p);
 
-	BUG_ON(rq != this_rq());
-	BUG_ON(p == current);
+	if (WARN_ON_ONCE(rq != this_rq()) ||
+	    WARN_ON_ONCE(p == current))
+		return;
+
 	lockdep_assert_held(&rq->lock);
 
 	if (!raw_spin_trylock(&p->pi_lock)) {
@@ -4948,7 +4950,7 @@ static void sd_free_ctl_entry(struct ctl
 }
 
 static int min_load_idx = 0;
-static int max_load_idx = CPU_LOAD_IDX_MAX;
+static int max_load_idx = CPU_LOAD_IDX_MAX-1;
 
 static void
 set_table_entry(struct ctl_table *entry,
diff -druNp linux-libre-3.8-gnu1/kernel/signal.c linux-libre-3.8.13-gnu1/kernel/signal.c
--- linux-libre-3.8-gnu1/kernel/signal.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/signal.c	2013-05-11 16:57:46.000000000 -0400
@@ -485,6 +485,9 @@ flush_signal_handlers(struct task_struct
 		if (force_default || ka->sa.sa_handler != SIG_IGN)
 			ka->sa.sa_handler = SIG_DFL;
 		ka->sa.sa_flags = 0;
+#ifdef __ARCH_HAS_SA_RESTORER
+		ka->sa.sa_restorer = NULL;
+#endif
 		sigemptyset(&ka->sa.sa_mask);
 		ka++;
 	}
@@ -2877,7 +2880,7 @@ do_send_specific(pid_t tgid, pid_t pid,
 
 static int do_tkill(pid_t tgid, pid_t pid, int sig)
 {
-	struct siginfo info;
+	struct siginfo info = {};
 
 	info.si_signo = sig;
 	info.si_errno = 0;
diff -druNp linux-libre-3.8-gnu1/kernel/sys.c linux-libre-3.8.13-gnu1/kernel/sys.c
--- linux-libre-3.8-gnu1/kernel/sys.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/sys.c	2013-05-11 16:57:46.000000000 -0400
@@ -323,7 +323,6 @@ void kernel_restart_prepare(char *cmd)
 	system_state = SYSTEM_RESTART;
 	usermodehelper_disable();
 	device_shutdown();
-	syscore_shutdown();
 }
 
 /**
@@ -369,6 +368,7 @@ void kernel_restart(char *cmd)
 {
 	kernel_restart_prepare(cmd);
 	disable_nonboot_cpus();
+	syscore_shutdown();
 	if (!cmd)
 		printk(KERN_EMERG "Restarting system.\n");
 	else
@@ -394,6 +394,7 @@ static void kernel_shutdown_prepare(enum
 void kernel_halt(void)
 {
 	kernel_shutdown_prepare(SYSTEM_HALT);
+	disable_nonboot_cpus();
 	syscore_shutdown();
 	printk(KERN_EMERG "System halted.\n");
 	kmsg_dump(KMSG_DUMP_HALT);
diff -druNp linux-libre-3.8-gnu1/kernel/sysctl_binary.c linux-libre-3.8.13-gnu1/kernel/sysctl_binary.c
--- linux-libre-3.8-gnu1/kernel/sysctl_binary.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/sysctl_binary.c	2013-05-11 16:57:46.000000000 -0400
@@ -1194,9 +1194,10 @@ static ssize_t bin_dn_node_address(struc
 
 		/* Convert the decnet address to binary */
 		result = -EIO;
-		nodep = strchr(buf, '.') + 1;
+		nodep = strchr(buf, '.');
 		if (!nodep)
 			goto out;
+		++nodep;
 
 		area = simple_strtoul(buf, NULL, 10);
 		node = simple_strtoul(nodep, NULL, 10);
diff -druNp linux-libre-3.8-gnu1/kernel/time/tick-broadcast.c linux-libre-3.8.13-gnu1/kernel/time/tick-broadcast.c
--- linux-libre-3.8-gnu1/kernel/time/tick-broadcast.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/time/tick-broadcast.c	2013-05-11 16:57:46.000000000 -0400
@@ -66,12 +66,17 @@ static void tick_broadcast_start_periodi
  */
 int tick_check_broadcast_device(struct clock_event_device *dev)
 {
-	if ((tick_broadcast_device.evtdev &&
+	struct clock_event_device *cur = tick_broadcast_device.evtdev;
+
+	if ((dev->features & CLOCK_EVT_FEAT_DUMMY) ||
+	    (tick_broadcast_device.evtdev &&
 	     tick_broadcast_device.evtdev->rating >= dev->rating) ||
 	     (dev->features & CLOCK_EVT_FEAT_C3STOP))
 		return 0;
 
 	clockevents_exchange_device(tick_broadcast_device.evtdev, dev);
+	if (cur)
+		cur->event_handler = clockevents_handle_noop;
 	tick_broadcast_device.evtdev = dev;
 	if (!cpumask_empty(tick_get_broadcast_mask()))
 		tick_broadcast_start_periodic(dev);
diff -druNp linux-libre-3.8-gnu1/kernel/time/tick-common.c linux-libre-3.8.13-gnu1/kernel/time/tick-common.c
--- linux-libre-3.8-gnu1/kernel/time/tick-common.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/time/tick-common.c	2013-05-11 16:57:46.000000000 -0400
@@ -323,6 +323,7 @@ static void tick_shutdown(unsigned int *
 		 */
 		dev->mode = CLOCK_EVT_MODE_UNUSED;
 		clockevents_exchange_device(dev, NULL);
+		dev->event_handler = clockevents_handle_noop;
 		td->evtdev = NULL;
 	}
 	raw_spin_unlock_irqrestore(&tick_device_lock, flags);
diff -druNp linux-libre-3.8-gnu1/kernel/time/tick-sched.c linux-libre-3.8.13-gnu1/kernel/time/tick-sched.c
--- linux-libre-3.8-gnu1/kernel/time/tick-sched.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/time/tick-sched.c	2013-05-11 16:57:46.000000000 -0400
@@ -564,14 +564,19 @@ void tick_nohz_idle_enter(void)
  */
 void tick_nohz_irq_exit(void)
 {
+	unsigned long flags;
 	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 
 	if (!ts->inidle)
 		return;
 
-	/* Cancel the timer because CPU already waken up from the C-states*/
+	local_irq_save(flags);
+
+	/* Cancel the timer because CPU already waken up from the C-states */
 	menu_hrtimer_cancel();
 	__tick_nohz_idle_enter(ts);
+
+	local_irq_restore(flags);
 }
 
 /**
diff -druNp linux-libre-3.8-gnu1/kernel/timeconst.pl linux-libre-3.8.13-gnu1/kernel/timeconst.pl
--- linux-libre-3.8-gnu1/kernel/timeconst.pl	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/timeconst.pl	2013-05-11 16:57:46.000000000 -0400
@@ -369,10 +369,8 @@ if ($hz eq '--can') {
 		die "Usage: $0 HZ\n";
 	}
 
-	@val = @{$canned_values{$hz}};
-	if (!defined(@val)) {
-		@val = compute_values($hz);
-	}
+	$cv = $canned_values{$hz};
+	@val = defined($cv) ? @$cv : compute_values($hz);
 	output($hz, @val);
 }
 exit 0;
diff -druNp linux-libre-3.8-gnu1/kernel/trace/ftrace.c linux-libre-3.8.13-gnu1/kernel/trace/ftrace.c
--- linux-libre-3.8-gnu1/kernel/trace/ftrace.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/ftrace.c	2013-05-11 16:57:46.000000000 -0400
@@ -650,7 +650,7 @@ int ftrace_profile_pages_init(struct ftr
 
 	pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE);
 
-	for (i = 0; i < pages; i++) {
+	for (i = 1; i < pages; i++) {
 		pg->next = (void *)get_zeroed_page(GFP_KERNEL);
 		if (!pg->next)
 			goto out_free;
@@ -668,7 +668,6 @@ int ftrace_profile_pages_init(struct ftr
 		free_page(tmp);
 	}
 
-	free_page((unsigned long)stat->pages);
 	stat->pages = NULL;
 	stat->start = NULL;
 
@@ -1028,6 +1027,19 @@ static __init void ftrace_profile_debugf
 
 static struct pid * const ftrace_swapper_pid = &init_struct_pid;
 
+loff_t
+ftrace_filter_lseek(struct file *file, loff_t offset, int whence)
+{
+	loff_t ret;
+
+	if (file->f_mode & FMODE_READ)
+		ret = seq_lseek(file, offset, whence);
+	else
+		file->f_pos = ret = 1;
+
+	return ret;
+}
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 #ifndef CONFIG_FTRACE_MCOUNT_RECORD
@@ -2590,7 +2602,7 @@ static void ftrace_filter_reset(struct f
  * routine, you can use ftrace_filter_write() for the write
  * routine if @flag has FTRACE_ITER_FILTER set, or
  * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
- * ftrace_regex_lseek() should be used as the lseek routine, and
+ * ftrace_filter_lseek() should be used as the lseek routine, and
  * release must call ftrace_regex_release().
  */
 int
@@ -2674,19 +2686,6 @@ ftrace_notrace_open(struct inode *inode,
 				 inode, file);
 }
 
-loff_t
-ftrace_regex_lseek(struct file *file, loff_t offset, int whence)
-{
-	loff_t ret;
-
-	if (file->f_mode & FMODE_READ)
-		ret = seq_lseek(file, offset, whence);
-	else
-		file->f_pos = ret = 1;
-
-	return ret;
-}
-
 static int ftrace_match(char *str, char *regex, int len, int type)
 {
 	int matched = 0;
@@ -3082,8 +3081,8 @@ __unregister_ftrace_function_probe(char
 					continue;
 			}
 
-			hlist_del(&entry->node);
-			call_rcu(&entry->rcu, ftrace_free_entry_rcu);
+			hlist_del_rcu(&entry->node);
+			call_rcu_sched(&entry->rcu, ftrace_free_entry_rcu);
 		}
 	}
 	__disable_ftrace_function_probe();
@@ -3549,7 +3548,7 @@ static const struct file_operations ftra
 	.open = ftrace_filter_open,
 	.read = seq_read,
 	.write = ftrace_filter_write,
-	.llseek = ftrace_regex_lseek,
+	.llseek = ftrace_filter_lseek,
 	.release = ftrace_regex_release,
 };
 
@@ -3557,7 +3556,7 @@ static const struct file_operations ftra
 	.open = ftrace_notrace_open,
 	.read = seq_read,
 	.write = ftrace_notrace_write,
-	.llseek = ftrace_regex_lseek,
+	.llseek = ftrace_filter_lseek,
 	.release = ftrace_regex_release,
 };
 
@@ -3715,7 +3714,8 @@ out:
 	if (fail)
 		return -EINVAL;
 
-	ftrace_graph_filter_enabled = 1;
+	ftrace_graph_filter_enabled = !!(*idx);
+
 	return 0;
 }
 
@@ -3762,8 +3762,8 @@ static const struct file_operations ftra
 	.open		= ftrace_graph_open,
 	.read		= seq_read,
 	.write		= ftrace_graph_write,
+	.llseek		= ftrace_filter_lseek,
 	.release	= ftrace_graph_release,
-	.llseek		= seq_lseek,
 };
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
@@ -3970,37 +3970,51 @@ static void ftrace_init_module(struct mo
 	ftrace_process_locs(mod, start, end);
 }
 
-static int ftrace_module_notify(struct notifier_block *self,
-				unsigned long val, void *data)
+static int ftrace_module_notify_enter(struct notifier_block *self,
+				      unsigned long val, void *data)
 {
 	struct module *mod = data;
 
-	switch (val) {
-	case MODULE_STATE_COMING:
+	if (val == MODULE_STATE_COMING)
 		ftrace_init_module(mod, mod->ftrace_callsites,
 				   mod->ftrace_callsites +
 				   mod->num_ftrace_callsites);
-		break;
-	case MODULE_STATE_GOING:
+	return 0;
+}
+
+static int ftrace_module_notify_exit(struct notifier_block *self,
+				     unsigned long val, void *data)
+{
+	struct module *mod = data;
+
+	if (val == MODULE_STATE_GOING)
 		ftrace_release_mod(mod);
-		break;
-	}
 
 	return 0;
 }
 #else
-static int ftrace_module_notify(struct notifier_block *self,
-				unsigned long val, void *data)
+static int ftrace_module_notify_enter(struct notifier_block *self,
+				      unsigned long val, void *data)
+{
+	return 0;
+}
+static int ftrace_module_notify_exit(struct notifier_block *self,
+				     unsigned long val, void *data)
 {
 	return 0;
 }
 #endif /* CONFIG_MODULES */
 
-struct notifier_block ftrace_module_nb = {
-	.notifier_call = ftrace_module_notify,
+struct notifier_block ftrace_module_enter_nb = {
+	.notifier_call = ftrace_module_notify_enter,
 	.priority = INT_MAX,	/* Run before anything that can use kprobes */
 };
 
+struct notifier_block ftrace_module_exit_nb = {
+	.notifier_call = ftrace_module_notify_exit,
+	.priority = INT_MIN,	/* Run after anything that can remove kprobes */
+};
+
 extern unsigned long __start_mcount_loc[];
 extern unsigned long __stop_mcount_loc[];
 
@@ -4032,9 +4046,13 @@ void __init ftrace_init(void)
 				  __start_mcount_loc,
 				  __stop_mcount_loc);
 
-	ret = register_module_notifier(&ftrace_module_nb);
+	ret = register_module_notifier(&ftrace_module_enter_nb);
 	if (ret)
-		pr_warning("Failed to register trace ftrace module notifier\n");
+		pr_warning("Failed to register trace ftrace module enter notifier\n");
+
+	ret = register_module_notifier(&ftrace_module_exit_nb);
+	if (ret)
+		pr_warning("Failed to register trace ftrace module exit notifier\n");
 
 	set_ftrace_early_filters();
 
@@ -4403,7 +4421,7 @@ static const struct file_operations ftra
 	.open		= ftrace_pid_open,
 	.write		= ftrace_pid_write,
 	.read		= seq_read,
-	.llseek		= seq_lseek,
+	.llseek		= ftrace_filter_lseek,
 	.release	= ftrace_pid_release,
 };
 
@@ -4519,12 +4537,8 @@ ftrace_enable_sysctl(struct ctl_table *t
 		ftrace_startup_sysctl();
 
 		/* we are starting ftrace again */
-		if (ftrace_ops_list != &ftrace_list_end) {
-			if (ftrace_ops_list->next == &ftrace_list_end)
-				ftrace_trace_function = ftrace_ops_list->func;
-			else
-				ftrace_trace_function = ftrace_ops_list_func;
-		}
+		if (ftrace_ops_list != &ftrace_list_end)
+			update_ftrace_function();
 
 	} else {
 		/* stopping ftrace calls (just send to ftrace_stub) */
diff -druNp linux-libre-3.8-gnu1/kernel/trace/Kconfig linux-libre-3.8.13-gnu1/kernel/trace/Kconfig
--- linux-libre-3.8-gnu1/kernel/trace/Kconfig	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/Kconfig	2013-05-11 16:57:46.000000000 -0400
@@ -416,24 +416,28 @@ config PROBE_EVENTS
 	def_bool n
 
 config DYNAMIC_FTRACE
-	bool "enable/disable ftrace tracepoints dynamically"
+	bool "enable/disable function tracing dynamically"
 	depends on FUNCTION_TRACER
 	depends on HAVE_DYNAMIC_FTRACE
 	default y
 	help
-          This option will modify all the calls to ftrace dynamically
-	  (will patch them out of the binary image and replace them
-	  with a No-Op instruction) as they are called. A table is
-	  created to dynamically enable them again.
+	  This option will modify all the calls to function tracing
+	  dynamically (will patch them out of the binary image and
+	  replace them with a No-Op instruction) on boot up. During
+	  compile time, a table is made of all the locations that ftrace
+	  can function trace, and this table is linked into the kernel
+	  image. When this is enabled, functions can be individually
+	  enabled, and the functions not enabled will not affect
+	  performance of the system.
+
+	  See the files in /sys/kernel/debug/tracing:
+	    available_filter_functions
+	    set_ftrace_filter
+	    set_ftrace_notrace
 
 	  This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but
 	  otherwise has native performance as long as no tracing is active.
 
-	  The changes to the code are done by a kernel thread that
-	  wakes up once a second and checks to see if any ftrace calls
-	  were made. If so, it runs stop_machine (stops all CPUS)
-	  and modifies the code to jump over the call to ftrace.
-
 config FUNCTION_PROFILER
 	bool "Kernel function profiler"
 	depends on FUNCTION_TRACER
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace.c linux-libre-3.8.13-gnu1/kernel/trace/trace.c
--- linux-libre-3.8-gnu1/kernel/trace/trace.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace.c	2013-05-11 16:57:46.000000000 -0400
@@ -703,7 +703,7 @@ __update_max_tr(struct trace_array *tr,
 void
 update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
-	struct ring_buffer *buf = tr->buffer;
+	struct ring_buffer *buf;
 
 	if (trace_stop_count)
 		return;
@@ -715,6 +715,7 @@ update_max_tr(struct trace_array *tr, st
 	}
 	arch_spin_lock(&ftrace_max_lock);
 
+	buf = tr->buffer;
 	tr->buffer = max_tr.buffer;
 	max_tr.buffer = buf;
 
@@ -2835,11 +2836,25 @@ static int set_tracer_option(struct trac
 	return -EINVAL;
 }
 
-static void set_tracer_flags(unsigned int mask, int enabled)
+/* Some tracers require overwrite to stay enabled */
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
+{
+	if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set)
+		return -1;
+
+	return 0;
+}
+
+int set_tracer_flag(unsigned int mask, int enabled)
 {
 	/* do nothing if flag is already set */
 	if (!!(trace_flags & mask) == !!enabled)
-		return;
+		return 0;
+
+	/* Give the tracer a chance to approve the change */
+	if (current_trace->flag_changed)
+		if (current_trace->flag_changed(current_trace, mask, !!enabled))
+			return -EINVAL;
 
 	if (enabled)
 		trace_flags |= mask;
@@ -2849,18 +2864,24 @@ static void set_tracer_flags(unsigned in
 	if (mask == TRACE_ITER_RECORD_CMD)
 		trace_event_enable_cmd_record(enabled);
 
-	if (mask == TRACE_ITER_OVERWRITE)
+	if (mask == TRACE_ITER_OVERWRITE) {
 		ring_buffer_change_overwrite(global_trace.buffer, enabled);
+#ifdef CONFIG_TRACER_MAX_TRACE
+		ring_buffer_change_overwrite(max_tr.buffer, enabled);
+#endif
+	}
 
 	if (mask == TRACE_ITER_PRINTK)
 		trace_printk_start_stop_comm(enabled);
+
+	return 0;
 }
 
 static int trace_set_options(char *option)
 {
 	char *cmp;
 	int neg = 0;
-	int ret = 0;
+	int ret = -ENODEV;
 	int i;
 
 	cmp = strstrip(option);
@@ -2870,19 +2891,20 @@ static int trace_set_options(char *optio
 		cmp += 2;
 	}
 
+	mutex_lock(&trace_types_lock);
+
 	for (i = 0; trace_options[i]; i++) {
 		if (strcmp(cmp, trace_options[i]) == 0) {
-			set_tracer_flags(1 << i, !neg);
+			ret = set_tracer_flag(1 << i, !neg);
 			break;
 		}
 	}
 
 	/* If no option could be set, test the specific tracer options */
-	if (!trace_options[i]) {
-		mutex_lock(&trace_types_lock);
+	if (!trace_options[i])
 		ret = set_tracer_option(current_trace, cmp, neg);
-		mutex_unlock(&trace_types_lock);
-	}
+
+	mutex_unlock(&trace_types_lock);
 
 	return ret;
 }
@@ -2892,6 +2914,7 @@ tracing_trace_options_write(struct file
 			size_t cnt, loff_t *ppos)
 {
 	char buf[64];
+	int ret;
 
 	if (cnt >= sizeof(buf))
 		return -EINVAL;
@@ -2901,7 +2924,9 @@ tracing_trace_options_write(struct file
 
 	buf[cnt] = 0;
 
-	trace_set_options(buf);
+	ret = trace_set_options(buf);
+	if (ret < 0)
+		return ret;
 
 	*ppos += cnt;
 
@@ -3207,6 +3232,9 @@ static int tracing_set_tracer(const char
 		goto out;
 
 	trace_branch_disable();
+
+	current_trace->enabled = false;
+
 	if (current_trace && current_trace->reset)
 		current_trace->reset(tr);
 	if (current_trace && current_trace->use_max_tr) {
@@ -3238,6 +3266,7 @@ static int tracing_set_tracer(const char
 	}
 
 	current_trace = t;
+	current_trace->enabled = true;
 	trace_branch_enable(tr);
  out:
 	mutex_unlock(&trace_types_lock);
@@ -4640,7 +4669,13 @@ trace_options_core_write(struct file *fi
 
 	if (val != 0 && val != 1)
 		return -EINVAL;
-	set_tracer_flags(1 << index, val);
+
+	mutex_lock(&trace_types_lock);
+	ret = set_tracer_flag(1 << index, val);
+	mutex_unlock(&trace_types_lock);
+
+	if (ret < 0)
+		return ret;
 
 	*ppos += cnt;
 
@@ -4850,6 +4885,8 @@ static __init int tracer_init_debugfs(vo
 	trace_access_lock_init();
 
 	d_tracer = tracing_init_dentry();
+	if (!d_tracer)
+		return 0;
 
 	trace_create_file("trace_options", 0644, d_tracer,
 			NULL, &tracing_iter_fops);
@@ -4983,36 +5020,32 @@ void trace_init_global_iter(struct trace
 	iter->cpu_file = TRACE_PIPE_ALL_CPU;
 }
 
-static void
-__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
+void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 {
-	static arch_spinlock_t ftrace_dump_lock =
-		(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 	/* use static because iter can be a bit big for the stack */
 	static struct trace_iterator iter;
+	static atomic_t dump_running;
 	unsigned int old_userobj;
-	static int dump_ran;
 	unsigned long flags;
 	int cnt = 0, cpu;
 
-	/* only one dump */
-	local_irq_save(flags);
-	arch_spin_lock(&ftrace_dump_lock);
-	if (dump_ran)
-		goto out;
-
-	dump_ran = 1;
+	/* Only allow one dump user at a time. */
+	if (atomic_inc_return(&dump_running) != 1) {
+		atomic_dec(&dump_running);
+		return;
+	}
 
+	/*
+	 * Always turn off tracing when we dump.
+	 * We don't need to show trace output of what happens
+	 * between multiple crashes.
+	 *
+	 * If the user does a sysrq-z, then they can re-enable
+	 * tracing with echo 1 > tracing_on.
+	 */
 	tracing_off();
 
-	/* Did function tracer already get disabled? */
-	if (ftrace_is_dead()) {
-		printk("# WARNING: FUNCTION TRACING IS CORRUPTED\n");
-		printk("#          MAY BE MISSING FUNCTION EVENTS\n");
-	}
-
-	if (disable_tracing)
-		ftrace_kill();
+	local_irq_save(flags);
 
 	trace_init_global_iter(&iter);
 
@@ -5045,6 +5078,12 @@ __ftrace_dump(bool disable_tracing, enum
 
 	printk(KERN_TRACE "Dumping ftrace buffer:\n");
 
+	/* Did function tracer already get disabled? */
+	if (ftrace_is_dead()) {
+		printk("# WARNING: FUNCTION TRACING IS CORRUPTED\n");
+		printk("#          MAY BE MISSING FUNCTION EVENTS\n");
+	}
+
 	/*
 	 * We need to stop all tracing on all CPUS to read the
 	 * the next buffer. This is a bit expensive, but is
@@ -5084,26 +5123,14 @@ __ftrace_dump(bool disable_tracing, enum
 		printk(KERN_TRACE "---------------------------------\n");
 
  out_enable:
-	/* Re-enable tracing if requested */
-	if (!disable_tracing) {
-		trace_flags |= old_userobj;
+	trace_flags |= old_userobj;
 
-		for_each_tracing_cpu(cpu) {
-			atomic_dec(&iter.tr->data[cpu]->disabled);
-		}
-		tracing_on();
+	for_each_tracing_cpu(cpu) {
+		atomic_dec(&iter.tr->data[cpu]->disabled);
 	}
-
- out:
-	arch_spin_unlock(&ftrace_dump_lock);
+ 	atomic_dec(&dump_running);
 	local_irq_restore(flags);
 }
-
-/* By default: disable tracing after the dump */
-void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
-{
-	__ftrace_dump(true, oops_dump_mode);
-}
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
 __init static int tracer_alloc_buffers(void)
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace.h linux-libre-3.8.13-gnu1/kernel/trace/trace.h
--- linux-libre-3.8-gnu1/kernel/trace/trace.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace.h	2013-05-11 16:57:46.000000000 -0400
@@ -283,10 +283,14 @@ struct tracer {
 	enum print_line_t	(*print_line)(struct trace_iterator *iter);
 	/* If you handled the flag setting, return 0 */
 	int			(*set_flag)(u32 old_flags, u32 bit, int set);
+	/* Return 0 if OK with change, else return non-zero */
+	int			(*flag_changed)(struct tracer *tracer,
+						u32 mask, int set);
 	struct tracer		*next;
 	struct tracer_flags	*flags;
 	bool			print_max;
 	bool			use_max_tr;
+	bool			enabled;
 };
 
 
@@ -835,6 +839,8 @@ extern const char *__stop___trace_bprint
 
 void trace_printk_init_buffers(void);
 void trace_printk_start_comm(void);
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
+int set_tracer_flag(unsigned int mask, int enabled);
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter)	\
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace_irqsoff.c linux-libre-3.8.13-gnu1/kernel/trace/trace_irqsoff.c
--- linux-libre-3.8-gnu1/kernel/trace/trace_irqsoff.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace_irqsoff.c	2013-05-11 16:57:46.000000000 -0400
@@ -32,7 +32,7 @@ enum {
 
 static int trace_type __read_mostly;
 
-static int save_lat_flag;
+static int save_flags;
 
 static void stop_irqsoff_tracer(struct trace_array *tr, int graph);
 static int start_irqsoff_tracer(struct trace_array *tr, int graph);
@@ -558,8 +558,11 @@ static void stop_irqsoff_tracer(struct t
 
 static void __irqsoff_tracer_init(struct trace_array *tr)
 {
-	save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
-	trace_flags |= TRACE_ITER_LATENCY_FMT;
+	save_flags = trace_flags;
+
+	/* non overwrite screws up the latency tracers */
+	set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
+	set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
 
 	tracing_max_latency = 0;
 	irqsoff_trace = tr;
@@ -573,10 +576,13 @@ static void __irqsoff_tracer_init(struct
 
 static void irqsoff_tracer_reset(struct trace_array *tr)
 {
+	int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
+	int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
+
 	stop_irqsoff_tracer(tr, is_graph());
 
-	if (!save_lat_flag)
-		trace_flags &= ~TRACE_ITER_LATENCY_FMT;
+	set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
+	set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
 }
 
 static void irqsoff_tracer_start(struct trace_array *tr)
@@ -609,6 +615,7 @@ static struct tracer irqsoff_tracer __re
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= irqsoff_set_flag,
+	.flag_changed	= trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_irqsoff,
 #endif
@@ -642,6 +649,7 @@ static struct tracer preemptoff_tracer _
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= irqsoff_set_flag,
+	.flag_changed	= trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_preemptoff,
 #endif
@@ -677,6 +685,7 @@ static struct tracer preemptirqsoff_trac
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= irqsoff_set_flag,
+	.flag_changed	= trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_preemptirqsoff,
 #endif
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace_sched_wakeup.c linux-libre-3.8.13-gnu1/kernel/trace/trace_sched_wakeup.c
--- linux-libre-3.8-gnu1/kernel/trace/trace_sched_wakeup.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace_sched_wakeup.c	2013-05-11 16:57:46.000000000 -0400
@@ -36,7 +36,7 @@ static void __wakeup_reset(struct trace_
 static int wakeup_graph_entry(struct ftrace_graph_ent *trace);
 static void wakeup_graph_return(struct ftrace_graph_ret *trace);
 
-static int save_lat_flag;
+static int save_flags;
 
 #define TRACE_DISPLAY_GRAPH     1
 
@@ -540,8 +540,11 @@ static void stop_wakeup_tracer(struct tr
 
 static int __wakeup_tracer_init(struct trace_array *tr)
 {
-	save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
-	trace_flags |= TRACE_ITER_LATENCY_FMT;
+	save_flags = trace_flags;
+
+	/* non overwrite screws up the latency tracers */
+	set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
+	set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
 
 	tracing_max_latency = 0;
 	wakeup_trace = tr;
@@ -563,12 +566,15 @@ static int wakeup_rt_tracer_init(struct
 
 static void wakeup_tracer_reset(struct trace_array *tr)
 {
+	int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
+	int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
+
 	stop_wakeup_tracer(tr);
 	/* make sure we put back any tasks we are tracing */
 	wakeup_reset(tr);
 
-	if (!save_lat_flag)
-		trace_flags &= ~TRACE_ITER_LATENCY_FMT;
+	set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
+	set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
 }
 
 static void wakeup_tracer_start(struct trace_array *tr)
@@ -594,6 +600,7 @@ static struct tracer wakeup_tracer __rea
 	.print_line	= wakeup_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= wakeup_set_flag,
+	.flag_changed	= trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_wakeup,
 #endif
@@ -615,6 +622,7 @@ static struct tracer wakeup_rt_tracer __
 	.print_line	= wakeup_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= wakeup_set_flag,
+	.flag_changed	= trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_wakeup,
 #endif
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace_selftest.c linux-libre-3.8.13-gnu1/kernel/trace/trace_selftest.c
--- linux-libre-3.8-gnu1/kernel/trace/trace_selftest.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace_selftest.c	2013-05-11 16:57:46.000000000 -0400
@@ -452,7 +452,6 @@ trace_selftest_function_recursion(void)
 	char *func_name;
 	int len;
 	int ret;
-	int cnt;
 
 	/* The previous test PASSED */
 	pr_cont("PASSED\n");
@@ -510,19 +509,10 @@ trace_selftest_function_recursion(void)
 
 	unregister_ftrace_function(&test_recsafe_probe);
 
-	/*
-	 * If arch supports all ftrace features, and no other task
-	 * was on the list, we should be fine.
-	 */
-	if (!ftrace_nr_registered_ops() && !FTRACE_FORCE_LIST_FUNC)
-		cnt = 2; /* Should have recursed */
-	else
-		cnt = 1;
-
 	ret = -1;
-	if (trace_selftest_recursion_cnt != cnt) {
-		pr_cont("*callback not called expected %d times (%d)* ",
-			cnt, trace_selftest_recursion_cnt);
+	if (trace_selftest_recursion_cnt != 2) {
+		pr_cont("*callback not called expected 2 times (%d)* ",
+			trace_selftest_recursion_cnt);
 		goto out;
 	}
 
@@ -712,8 +702,6 @@ trace_selftest_startup_function(struct t
 /* Maximum number of functions to trace before diagnosing a hang */
 #define GRAPH_MAX_FUNC_TEST	100000000
 
-static void
-__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode);
 static unsigned int graph_hang_thresh;
 
 /* Wrap the real function entry probe to avoid possible hanging */
@@ -723,8 +711,11 @@ static int trace_graph_entry_watchdog(st
 	if (unlikely(++graph_hang_thresh > GRAPH_MAX_FUNC_TEST)) {
 		ftrace_graph_stop();
 		printk(KERN_WARNING "BUG: Function graph tracer hang!\n");
-		if (ftrace_dump_on_oops)
-			__ftrace_dump(false, DUMP_ALL);
+		if (ftrace_dump_on_oops) {
+			ftrace_dump(DUMP_ALL);
+			/* ftrace_dump() disables tracing */
+			tracing_on();
+		}
 		return 0;
 	}
 
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace_stack.c linux-libre-3.8.13-gnu1/kernel/trace/trace_stack.c
--- linux-libre-3.8-gnu1/kernel/trace/trace_stack.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace_stack.c	2013-05-11 16:57:46.000000000 -0400
@@ -20,13 +20,24 @@
 
 #define STACK_TRACE_ENTRIES 500
 
+#ifdef CC_USING_FENTRY
+# define fentry		1
+#else
+# define fentry		0
+#endif
+
 static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] =
 	 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX };
 static unsigned stack_dump_index[STACK_TRACE_ENTRIES];
 
+/*
+ * Reserve one entry for the passed in ip. This will allow
+ * us to remove most or all of the stack size overhead
+ * added by the stack tracer itself.
+ */
 static struct stack_trace max_stack_trace = {
-	.max_entries		= STACK_TRACE_ENTRIES,
-	.entries		= stack_dump_trace,
+	.max_entries		= STACK_TRACE_ENTRIES - 1,
+	.entries		= &stack_dump_trace[1],
 };
 
 static unsigned long max_stack_size;
@@ -39,25 +50,34 @@ static DEFINE_MUTEX(stack_sysctl_mutex);
 int stack_tracer_enabled;
 static int last_stack_tracer_enabled;
 
-static inline void check_stack(void)
+static inline void
+check_stack(unsigned long ip, unsigned long *stack)
 {
 	unsigned long this_size, flags;
 	unsigned long *p, *top, *start;
+	static int tracer_frame;
+	int frame_size = ACCESS_ONCE(tracer_frame);
 	int i;
 
-	this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1);
+	this_size = ((unsigned long)stack) & (THREAD_SIZE-1);
 	this_size = THREAD_SIZE - this_size;
+	/* Remove the frame of the tracer */
+	this_size -= frame_size;
 
 	if (this_size <= max_stack_size)
 		return;
 
 	/* we do not handle interrupt stacks yet */
-	if (!object_is_on_stack(&this_size))
+	if (!object_is_on_stack(stack))
 		return;
 
 	local_irq_save(flags);
 	arch_spin_lock(&max_stack_lock);
 
+	/* In case another CPU set the tracer_frame on us */
+	if (unlikely(!frame_size))
+		this_size -= tracer_frame;
+
 	/* a race could have already updated it */
 	if (this_size <= max_stack_size)
 		goto out;
@@ -70,10 +90,18 @@ static inline void check_stack(void)
 	save_stack_trace(&max_stack_trace);
 
 	/*
+	 * Add the passed in ip from the function tracer.
+	 * Searching for this on the stack will skip over
+	 * most of the overhead from the stack tracer itself.
+	 */
+	stack_dump_trace[0] = ip;
+	max_stack_trace.nr_entries++;
+
+	/*
 	 * Now find where in the stack these are.
 	 */
 	i = 0;
-	start = &this_size;
+	start = stack;
 	top = (unsigned long *)
 		(((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE);
 
@@ -97,6 +125,18 @@ static inline void check_stack(void)
 				found = 1;
 				/* Start the search from here */
 				start = p + 1;
+				/*
+				 * We do not want to show the overhead
+				 * of the stack tracer stack in the
+				 * max stack. If we haven't figured
+				 * out what that is, then figure it out
+				 * now.
+				 */
+				if (unlikely(!tracer_frame) && i == 1) {
+					tracer_frame = (p - stack) *
+						sizeof(unsigned long);
+					max_stack_size -= tracer_frame;
+				}
 			}
 		}
 
@@ -113,6 +153,7 @@ static void
 stack_trace_call(unsigned long ip, unsigned long parent_ip,
 		 struct ftrace_ops *op, struct pt_regs *pt_regs)
 {
+	unsigned long stack;
 	int cpu;
 
 	preempt_disable_notrace();
@@ -122,7 +163,26 @@ stack_trace_call(unsigned long ip, unsig
 	if (per_cpu(trace_active, cpu)++ != 0)
 		goto out;
 
-	check_stack();
+	/*
+	 * When fentry is used, the traced function does not get
+	 * its stack frame set up, and we lose the parent.
+	 * The ip is pretty useless because the function tracer
+	 * was called before that function set up its stack frame.
+	 * In this case, we use the parent ip.
+	 *
+	 * By adding the return address of either the parent ip
+	 * or the current ip we can disregard most of the stack usage
+	 * caused by the stack tracer itself.
+	 *
+	 * The function tracer always reports the address of where the
+	 * mcount call was, but the stack will hold the return address.
+	 */
+	if (fentry)
+		ip = parent_ip;
+	else
+		ip += MCOUNT_INSN_SIZE;
+
+	check_stack(ip, &stack);
 
  out:
 	per_cpu(trace_active, cpu)--;
@@ -322,7 +382,7 @@ static const struct file_operations stac
 	.open = stack_trace_filter_open,
 	.read = seq_read,
 	.write = ftrace_filter_write,
-	.llseek = ftrace_regex_lseek,
+	.llseek = ftrace_filter_lseek,
 	.release = ftrace_regex_release,
 };
 
@@ -371,6 +431,8 @@ static __init int stack_trace_init(void)
 	struct dentry *d_tracer;
 
 	d_tracer = tracing_init_dentry();
+	if (!d_tracer)
+		return 0;
 
 	trace_create_file("stack_max_size", 0644, d_tracer,
 			&max_stack_size, &stack_max_size_fops);
diff -druNp linux-libre-3.8-gnu1/kernel/trace/trace_stat.c linux-libre-3.8.13-gnu1/kernel/trace/trace_stat.c
--- linux-libre-3.8-gnu1/kernel/trace/trace_stat.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/trace/trace_stat.c	2013-05-11 16:57:46.000000000 -0400
@@ -307,6 +307,8 @@ static int tracing_stat_init(void)
 	struct dentry *d_tracing;
 
 	d_tracing = tracing_init_dentry();
+	if (!d_tracing)
+		return 0;
 
 	stat_dir = debugfs_create_dir("trace_stat", d_tracing);
 	if (!stat_dir)
diff -druNp linux-libre-3.8-gnu1/kernel/user.c linux-libre-3.8.13-gnu1/kernel/user.c
--- linux-libre-3.8-gnu1/kernel/user.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/user.c	2013-05-11 16:57:46.000000000 -0400
@@ -53,6 +53,8 @@ struct user_namespace init_user_ns = {
 	.owner = GLOBAL_ROOT_UID,
 	.group = GLOBAL_ROOT_GID,
 	.proc_inum = PROC_USER_INIT_INO,
+	.may_mount_sysfs = true,
+	.may_mount_proc = true,
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
diff -druNp linux-libre-3.8-gnu1/kernel/user_namespace.c linux-libre-3.8.13-gnu1/kernel/user_namespace.c
--- linux-libre-3.8-gnu1/kernel/user_namespace.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/user_namespace.c	2013-05-11 16:57:46.000000000 -0400
@@ -21,10 +21,12 @@
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/projid.h>
+#include <linux/fs_struct.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
-static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
+static bool new_idmap_permitted(const struct file *file,
+				struct user_namespace *ns, int cap_setid,
 				struct uid_gid_map *map);
 
 static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
@@ -60,6 +62,15 @@ int create_user_ns(struct cred *new)
 	kgid_t group = new->egid;
 	int ret;
 
+	/*
+	 * Verify that we can not violate the policy of which files
+	 * may be accessed that is specified by the root directory,
+	 * by verifing that the root directory is at the root of the
+	 * mount namespace which allows all files to be accessed.
+	 */
+	if (current_chrooted())
+		return -EPERM;
+
 	/* The creator needs a mapping in the parent user namespace
 	 * or else we won't be able to reasonably tell userspace who
 	 * created a user_namespace.
@@ -86,6 +97,8 @@ int create_user_ns(struct cred *new)
 
 	set_cred_user_ns(new, ns);
 
+	update_mnt_policy(ns);
+
 	return 0;
 }
 
@@ -563,10 +576,10 @@ static ssize_t map_write(struct file *fi
 	if (map->nr_extents != 0)
 		goto out;
 
-	/* Require the appropriate privilege CAP_SETUID or CAP_SETGID
-	 * over the user namespace in order to set the id mapping.
+	/*
+	 * Adjusting namespace settings requires capabilities on the target.
 	 */
-	if (cap_valid(cap_setid) && !ns_capable(ns, cap_setid))
+	if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
 		goto out;
 
 	/* Get a buffer */
@@ -654,7 +667,7 @@ static ssize_t map_write(struct file *fi
 
 	ret = -EPERM;
 	/* Validate the user is allowed to use user id's mapped to. */
-	if (!new_idmap_permitted(ns, cap_setid, &new_map))
+	if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
 		goto out;
 
 	/* Map the lower ids from the parent user namespace to the
@@ -741,7 +754,8 @@ ssize_t proc_projid_map_write(struct fil
 			 &ns->projid_map, &ns->parent->projid_map);
 }
 
-static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
+static bool new_idmap_permitted(const struct file *file,
+				struct user_namespace *ns, int cap_setid,
 				struct uid_gid_map *new_map)
 {
 	/* Allow mapping to your own filesystem ids */
@@ -749,12 +763,12 @@ static bool new_idmap_permitted(struct u
 		u32 id = new_map->extent[0].lower_first;
 		if (cap_setid == CAP_SETUID) {
 			kuid_t uid = make_kuid(ns->parent, id);
-			if (uid_eq(uid, current_fsuid()))
+			if (uid_eq(uid, file->f_cred->fsuid))
 				return true;
 		}
 		else if (cap_setid == CAP_SETGID) {
 			kgid_t gid = make_kgid(ns->parent, id);
-			if (gid_eq(gid, current_fsgid()))
+			if (gid_eq(gid, file->f_cred->fsgid))
 				return true;
 		}
 	}
@@ -765,8 +779,10 @@ static bool new_idmap_permitted(struct u
 
 	/* Allow the specified ids if we have the appropriate capability
 	 * (CAP_SETUID or CAP_SETGID) over the parent user namespace.
+	 * And the opener of the id file also had the approprpiate capability.
 	 */
-	if (ns_capable(ns->parent, cap_setid))
+	if (ns_capable(ns->parent, cap_setid) &&
+	    file_ns_capable(file, ns->parent, cap_setid))
 		return true;
 
 	return false;
@@ -803,6 +819,9 @@ static int userns_install(struct nsproxy
 	if (atomic_read(&current->mm->mm_users) > 1)
 		return -EINVAL;
 
+	if (current->fs->users != 1)
+		return -EINVAL;
+
 	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
diff -druNp linux-libre-3.8-gnu1/kernel/workqueue.c linux-libre-3.8.13-gnu1/kernel/workqueue.c
--- linux-libre-3.8-gnu1/kernel/workqueue.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/kernel/workqueue.c	2013-05-11 16:57:46.000000000 -0400
@@ -138,6 +138,7 @@ struct worker {
 	};
 
 	struct work_struct	*current_work;	/* L: work being processed */
+	work_func_t		current_func;	/* L: current_work's fn */
 	struct cpu_workqueue_struct *current_cwq; /* L: current_work's cwq */
 	struct list_head	scheduled;	/* L: scheduled works */
 	struct task_struct	*task;		/* I: worker task */
@@ -910,7 +911,8 @@ static struct worker *__find_worker_exec
 	struct hlist_node *tmp;
 
 	hlist_for_each_entry(worker, tmp, bwh, hentry)
-		if (worker->current_work == work)
+		if (worker->current_work == work &&
+		    worker->current_func == work->func)
 			return worker;
 	return NULL;
 }
@@ -920,9 +922,27 @@ static struct worker *__find_worker_exec
  * @gcwq: gcwq of interest
  * @work: work to find worker for
  *
- * Find a worker which is executing @work on @gcwq.  This function is
- * identical to __find_worker_executing_work() except that this
- * function calculates @bwh itself.
+ * Find a worker which is executing @work on @gcwq by searching
+ * @gcwq->busy_hash which is keyed by the address of @work.  For a worker
+ * to match, its current execution should match the address of @work and
+ * its work function.  This is to avoid unwanted dependency between
+ * unrelated work executions through a work item being recycled while still
+ * being executed.
+ *
+ * This is a bit tricky.  A work item may be freed once its execution
+ * starts and nothing prevents the freed area from being recycled for
+ * another work item.  If the same work item address ends up being reused
+ * before the original execution finishes, workqueue will identify the
+ * recycled work item as currently executing and make it wait until the
+ * current execution finishes, introducing an unwanted dependency.
+ *
+ * This function checks the work item address, work function and workqueue
+ * to avoid false positives.  Note that this isn't complete as one may
+ * construct a work function which can introduce dependency onto itself
+ * through a recycled work item.  Well, if somebody wants to shoot oneself
+ * in the foot that badly, there's only so much we can do, and if such
+ * deadlock actually occurs, it should be easy to locate the culprit work
+ * function.
  *
  * CONTEXT:
  * spin_lock_irq(gcwq->lock).
@@ -1352,7 +1372,7 @@ void delayed_work_timer_fn(unsigned long
 	/* should have been called from irqsafe timer with irq already off */
 	__queue_work(dwork->cpu, cwq->wq, &dwork->work);
 }
-EXPORT_SYMBOL_GPL(delayed_work_timer_fn);
+EXPORT_SYMBOL(delayed_work_timer_fn);
 
 static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
 				struct delayed_work *dwork, unsigned long delay)
@@ -2168,7 +2188,6 @@ __acquires(&gcwq->lock)
 	struct global_cwq *gcwq = pool->gcwq;
 	struct hlist_head *bwh = busy_worker_head(gcwq, work);
 	bool cpu_intensive = cwq->wq->flags & WQ_CPU_INTENSIVE;
-	work_func_t f = work->func;
 	int work_color;
 	struct worker *collision;
 #ifdef CONFIG_LOCKDEP
@@ -2208,6 +2227,7 @@ __acquires(&gcwq->lock)
 	debug_work_deactivate(work);
 	hlist_add_head(&worker->hentry, bwh);
 	worker->current_work = work;
+	worker->current_func = work->func;
 	worker->current_cwq = cwq;
 	work_color = get_work_color(work);
 
@@ -2240,7 +2260,7 @@ __acquires(&gcwq->lock)
 	lock_map_acquire_read(&cwq->wq->lockdep_map);
 	lock_map_acquire(&lockdep_map);
 	trace_workqueue_execute_start(work);
-	f(work);
+	worker->current_func(work);
 	/*
 	 * While we must be careful to not use "work" after this, the trace
 	 * point will only record its address.
@@ -2252,7 +2272,8 @@ __acquires(&gcwq->lock)
 	if (unlikely(in_atomic() || lockdep_depth(current) > 0)) {
 		pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d\n"
 		       "     last function: %pf\n",
-		       current->comm, preempt_count(), task_pid_nr(current), f);
+		       current->comm, preempt_count(), task_pid_nr(current),
+		       worker->current_func);
 		debug_show_held_locks(current);
 		dump_stack();
 	}
@@ -2266,6 +2287,7 @@ __acquires(&gcwq->lock)
 	/* we're done with it, release */
 	hlist_del_init(&worker->hentry);
 	worker->current_work = NULL;
+	worker->current_func = NULL;
 	worker->current_cwq = NULL;
 	cwq_dec_nr_in_flight(cwq, work_color);
 }
diff -druNp linux-libre-3.8-gnu1/lib/idr.c linux-libre-3.8.13-gnu1/lib/idr.c
--- linux-libre-3.8-gnu1/lib/idr.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/lib/idr.c	2013-05-11 16:57:46.000000000 -0400
@@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int
 			return p;
 		}
 
-		id += 1 << n;
+		/*
+		 * Proceed to the next layer at the current level.  Unlike
+		 * idr_for_each(), @id isn't guaranteed to be aligned to
+		 * layer boundary at this point and adding 1 << n may
+		 * incorrectly skip IDs.  Make sure we jump to the
+		 * beginning of the next layer using round_up().
+		 */
+		id = round_up(id + 1, 1 << n);
 		while (n < fls(id)) {
 			n += IDR_BITS;
 			p = *--paa;
diff -druNp linux-libre-3.8-gnu1/lib/kobject.c linux-libre-3.8.13-gnu1/lib/kobject.c
--- linux-libre-3.8-gnu1/lib/kobject.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/lib/kobject.c	2013-05-11 16:57:46.000000000 -0400
@@ -529,6 +529,13 @@ struct kobject *kobject_get(struct kobje
 	return kobj;
 }
 
+static struct kobject *kobject_get_unless_zero(struct kobject *kobj)
+{
+	if (!kref_get_unless_zero(&kobj->kref))
+		kobj = NULL;
+	return kobj;
+}
+
 /*
  * kobject_cleanup - free kobject resources.
  * @kobj: object to cleanup
@@ -751,7 +758,7 @@ struct kobject *kset_find_obj(struct kse
 
 	list_for_each_entry(k, &kset->list, entry) {
 		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
-			ret = kobject_get(k);
+			ret = kobject_get_unless_zero(k);
 			break;
 		}
 	}
diff -druNp linux-libre-3.8-gnu1/lib/oid_registry.c linux-libre-3.8.13-gnu1/lib/oid_registry.c
--- linux-libre-3.8-gnu1/lib/oid_registry.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/lib/oid_registry.c	2013-05-11 16:57:46.000000000 -0400
@@ -9,6 +9,7 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#include <linux/module.h>
 #include <linux/export.h>
 #include <linux/oid_registry.h>
 #include <linux/kernel.h>
@@ -16,6 +17,10 @@
 #include <linux/bug.h>
 #include "oid_registry_data.c"
 
+MODULE_DESCRIPTION("OID Registry");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
 /**
  * look_up_OID - Find an OID registration for the specified data
  * @data: Binary representation of the OID
diff -druNp linux-libre-3.8-gnu1/Makefile linux-libre-3.8.13-gnu1/Makefile
--- linux-libre-3.8-gnu1/Makefile	2013-05-01 16:37:02.000000000 -0400
+++ linux-libre-3.8.13-gnu1/Makefile	2013-05-11 19:13:03.000000000 -0400
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 8
-SUBLEVEL = 0
+SUBLEVEL = 13
 EXTRAVERSION =-gnu1
-NAME = Unicycling Gorilla
+NAME = Displaced Humerus Anterior
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -druNp linux-libre-3.8-gnu1/mm/fadvise.c linux-libre-3.8.13-gnu1/mm/fadvise.c
--- linux-libre-3.8-gnu1/mm/fadvise.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/fadvise.c	2013-05-11 16:57:46.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/fadvise.h>
 #include <linux/writeback.h>
 #include <linux/syscalls.h>
+#include <linux/swap.h>
 
 #include <asm/unistd.h>
 
@@ -120,9 +121,22 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, lof
 		start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT;
 		end_index = (endbyte >> PAGE_CACHE_SHIFT);
 
-		if (end_index >= start_index)
-			invalidate_mapping_pages(mapping, start_index,
+		if (end_index >= start_index) {
+			unsigned long count = invalidate_mapping_pages(mapping,
+						start_index, end_index);
+
+			/*
+			 * If fewer pages were invalidated than expected then
+			 * it is possible that some of the pages were on
+			 * a per-cpu pagevec for a remote CPU. Drain all
+			 * pagevecs and try again.
+			 */
+			if (count < (end_index - start_index + 1)) {
+				lru_add_drain_all();
+				invalidate_mapping_pages(mapping, start_index,
 						end_index);
+			}
+		}
 		break;
 	default:
 		ret = -EINVAL;
diff -druNp linux-libre-3.8-gnu1/mm/hugetlb.c linux-libre-3.8.13-gnu1/mm/hugetlb.c
--- linux-libre-3.8-gnu1/mm/hugetlb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/hugetlb.c	2013-05-11 16:57:46.000000000 -0400
@@ -2127,8 +2127,12 @@ int hugetlb_report_node_meminfo(int nid,
 /* Return the number pages of memory we physically have, in PAGE_SIZE units. */
 unsigned long hugetlb_total_pages(void)
 {
-	struct hstate *h = &default_hstate;
-	return h->nr_huge_pages * pages_per_huge_page(h);
+	struct hstate *h;
+	unsigned long nr_total_pages = 0;
+
+	for_each_hstate(h)
+		nr_total_pages += h->nr_huge_pages * pages_per_huge_page(h);
+	return nr_total_pages;
 }
 
 static int hugetlb_acct_memory(struct hstate *h, long delta)
@@ -2961,7 +2965,17 @@ int follow_hugetlb_page(struct mm_struct
 			break;
 		}
 
-		if (absent ||
+		/*
+		 * We need call hugetlb_fault for both hugepages under migration
+		 * (in which case hugetlb_fault waits for the migration,) and
+		 * hwpoisoned hugepages (in which case we need to prevent the
+		 * caller from accessing to them.) In order to do this, we use
+		 * here is_swap_pte instead of is_hugetlb_entry_migration and
+		 * is_hugetlb_entry_hwpoisoned. This is because it simply covers
+		 * both cases, and because we can't follow correct pages
+		 * directly from any kind of swap entries.
+		 */
+		if (absent || is_swap_pte(huge_ptep_get(pte)) ||
 		    ((flags & FOLL_WRITE) && !pte_write(huge_ptep_get(pte)))) {
 			int ret;
 
diff -druNp linux-libre-3.8-gnu1/mm/memory.c linux-libre-3.8.13-gnu1/mm/memory.c
--- linux-libre-3.8-gnu1/mm/memory.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/memory.c	2013-05-11 16:57:46.000000000 -0400
@@ -212,6 +212,7 @@ void tlb_gather_mmu(struct mmu_gather *t
 	tlb->mm = mm;
 
 	tlb->fullmm     = fullmm;
+	tlb->need_flush_all = 0;
 	tlb->start	= -1UL;
 	tlb->end	= 0;
 	tlb->need_flush = 0;
@@ -2357,6 +2358,53 @@ int remap_pfn_range(struct vm_area_struc
 }
 EXPORT_SYMBOL(remap_pfn_range);
 
+/**
+ * vm_iomap_memory - remap memory to userspace
+ * @vma: user vma to map to
+ * @start: start of area
+ * @len: size of area
+ *
+ * This is a simplified io_remap_pfn_range() for common driver use. The
+ * driver just needs to give us the physical memory range to be mapped,
+ * we'll figure out the rest from the vma information.
+ *
+ * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get
+ * whatever write-combining details or similar.
+ */
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len)
+{
+	unsigned long vm_len, pfn, pages;
+
+	/* Check that the physical memory area passed in looks valid */
+	if (start + len < start)
+		return -EINVAL;
+	/*
+	 * You *really* shouldn't map things that aren't page-aligned,
+	 * but we've historically allowed it because IO memory might
+	 * just have smaller alignment.
+	 */
+	len += start & ~PAGE_MASK;
+	pfn = start >> PAGE_SHIFT;
+	pages = (len + ~PAGE_MASK) >> PAGE_SHIFT;
+	if (pfn + pages < pfn)
+		return -EINVAL;
+
+	/* We start the mapping 'vm_pgoff' pages into the area */
+	if (vma->vm_pgoff > pages)
+		return -EINVAL;
+	pfn += vma->vm_pgoff;
+	pages -= vma->vm_pgoff;
+
+	/* Can we fit all of the mapping? */
+	vm_len = vma->vm_end - vma->vm_start;
+	if (vm_len >> PAGE_SHIFT > pages)
+		return -EINVAL;
+
+	/* Ok, let it rip */
+	return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_iomap_memory);
+
 static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
 				     unsigned long addr, unsigned long end,
 				     pte_fn_t fn, void *data)
diff -druNp linux-libre-3.8-gnu1/mm/mempolicy.c linux-libre-3.8.13-gnu1/mm/mempolicy.c
--- linux-libre-3.8-gnu1/mm/mempolicy.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/mempolicy.c	2013-05-11 16:57:46.000000000 -0400
@@ -2386,8 +2386,8 @@ restart:
 				*mpol_new = *n->policy;
 				atomic_set(&mpol_new->refcnt, 1);
 				sp_node_init(n_new, n->end, end, mpol_new);
-				sp_insert(sp, n_new);
 				n->end = start;
+				sp_insert(sp, n_new);
 				n_new = NULL;
 				mpol_new = NULL;
 				break;
diff -druNp linux-libre-3.8-gnu1/mm/mmap.c linux-libre-3.8.13-gnu1/mm/mmap.c
--- linux-libre-3.8-gnu1/mm/mmap.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/mmap.c	2013-05-11 16:57:46.000000000 -0400
@@ -1296,15 +1296,20 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned lon
 		file = fget(fd);
 		if (!file)
 			goto out;
+		if (is_file_hugepages(file))
+			len = ALIGN(len, huge_page_size(hstate_file(file)));
 	} else if (flags & MAP_HUGETLB) {
 		struct user_struct *user = NULL;
+
+		len = ALIGN(len, huge_page_size(hstate_sizelog(
+			(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK)));
 		/*
 		 * VM_NORESERVE is used because the reservations will be
 		 * taken when vm_ops->mmap() is called
 		 * A dummy user value is used because we are not locking
 		 * memory so no accounting is necessary
 		 */
-		file = hugetlb_file_setup(HUGETLB_ANON_FILE, addr, len,
+		file = hugetlb_file_setup(HUGETLB_ANON_FILE, len,
 				VM_NORESERVE,
 				&user, HUGETLB_ANONHUGE_INODE,
 				(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
@@ -1922,7 +1927,7 @@ struct vm_area_struct *find_vma(struct m
 
 	/* Check the cache first. */
 	/* (Cache hit rate is typically around 35%.) */
-	vma = mm->mmap_cache;
+	vma = ACCESS_ONCE(mm->mmap_cache);
 	if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
 		struct rb_node *rb_node;
 
@@ -2169,9 +2174,28 @@ int expand_downwards(struct vm_area_stru
 	return error;
 }
 
+/*
+ * Note how expand_stack() refuses to expand the stack all the way to
+ * abut the next virtual mapping, *unless* that mapping itself is also
+ * a stack mapping. We want to leave room for a guard page, after all
+ * (the guard page itself is not added here, that is done by the
+ * actual page faulting logic)
+ *
+ * This matches the behavior of the guard page logic (see mm/memory.c:
+ * check_stack_guard_page()), which only allows the guard page to be
+ * removed under these circumstances.
+ */
 #ifdef CONFIG_STACK_GROWSUP
 int expand_stack(struct vm_area_struct *vma, unsigned long address)
 {
+	struct vm_area_struct *next;
+
+	address &= PAGE_MASK;
+	next = vma->vm_next;
+	if (next && next->vm_start == address + PAGE_SIZE) {
+		if (!(next->vm_flags & VM_GROWSUP))
+			return -ENOMEM;
+	}
 	return expand_upwards(vma, address);
 }
 
@@ -2194,6 +2218,14 @@ find_extend_vma(struct mm_struct *mm, un
 #else
 int expand_stack(struct vm_area_struct *vma, unsigned long address)
 {
+	struct vm_area_struct *prev;
+
+	address &= PAGE_MASK;
+	prev = vma->vm_prev;
+	if (prev && prev->vm_end == address) {
+		if (!(prev->vm_flags & VM_GROWSDOWN))
+			return -ENOMEM;
+	}
 	return expand_downwards(vma, address);
 }
 
@@ -2262,7 +2294,7 @@ static void unmap_region(struct mm_struc
 	update_hiwater_rss(mm);
 	unmap_vmas(&tlb, vma, start, end);
 	free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
-				 next ? next->vm_start : 0);
+				 next ? next->vm_start : USER_PGTABLES_CEILING);
 	tlb_finish_mmu(&tlb, start, end);
 }
 
@@ -2640,7 +2672,7 @@ void exit_mmap(struct mm_struct *mm)
 	/* Use -1 here to ensure all VMAs in the mm are unmapped */
 	unmap_vmas(&tlb, vma, 0, -1);
 
-	free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
+	free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, USER_PGTABLES_CEILING);
 	tlb_finish_mmu(&tlb, 0, -1);
 
 	/*
diff -druNp linux-libre-3.8-gnu1/mm/mmu_notifier.c linux-libre-3.8.13-gnu1/mm/mmu_notifier.c
--- linux-libre-3.8-gnu1/mm/mmu_notifier.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/mmu_notifier.c	2013-05-11 16:57:46.000000000 -0400
@@ -37,49 +37,51 @@ static struct srcu_struct srcu;
 void __mmu_notifier_release(struct mm_struct *mm)
 {
 	struct mmu_notifier *mn;
-	struct hlist_node *n;
 	int id;
 
 	/*
-	 * SRCU here will block mmu_notifier_unregister until
-	 * ->release returns.
+	 * srcu_read_lock() here will block synchronize_srcu() in
+	 * mmu_notifier_unregister() until all registered
+	 * ->release() callouts this function makes have
+	 * returned.
 	 */
 	id = srcu_read_lock(&srcu);
-	hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist)
-		/*
-		 * if ->release runs before mmu_notifier_unregister it
-		 * must be handled as it's the only way for the driver
-		 * to flush all existing sptes and stop the driver
-		 * from establishing any more sptes before all the
-		 * pages in the mm are freed.
-		 */
-		if (mn->ops->release)
-			mn->ops->release(mn, mm);
-	srcu_read_unlock(&srcu, id);
-
 	spin_lock(&mm->mmu_notifier_mm->lock);
 	while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) {
 		mn = hlist_entry(mm->mmu_notifier_mm->list.first,
 				 struct mmu_notifier,
 				 hlist);
+
 		/*
-		 * We arrived before mmu_notifier_unregister so
-		 * mmu_notifier_unregister will do nothing other than
-		 * to wait ->release to finish and
-		 * mmu_notifier_unregister to return.
+		 * Unlink.  This will prevent mmu_notifier_unregister()
+		 * from also making the ->release() callout.
 		 */
 		hlist_del_init_rcu(&mn->hlist);
+		spin_unlock(&mm->mmu_notifier_mm->lock);
+
+		/*
+		 * Clear sptes. (see 'release' description in mmu_notifier.h)
+		 */
+		if (mn->ops->release)
+			mn->ops->release(mn, mm);
+
+		spin_lock(&mm->mmu_notifier_mm->lock);
 	}
 	spin_unlock(&mm->mmu_notifier_mm->lock);
 
 	/*
-	 * synchronize_srcu here prevents mmu_notifier_release to
-	 * return to exit_mmap (which would proceed freeing all pages
-	 * in the mm) until the ->release method returns, if it was
-	 * invoked by mmu_notifier_unregister.
-	 *
-	 * The mmu_notifier_mm can't go away from under us because one
-	 * mm_count is hold by exit_mmap.
+	 * All callouts to ->release() which we have done are complete.
+	 * Allow synchronize_srcu() in mmu_notifier_unregister() to complete
+	 */
+	srcu_read_unlock(&srcu, id);
+
+	/*
+	 * mmu_notifier_unregister() may have unlinked a notifier and may
+	 * still be calling out to it.	Additionally, other notifiers
+	 * may have been active via vmtruncate() et. al. Block here
+	 * to ensure that all notifier callouts for this mm have been
+	 * completed and the sptes are really cleaned up before returning
+	 * to exit_mmap().
 	 */
 	synchronize_srcu(&srcu);
 }
@@ -294,31 +296,31 @@ void mmu_notifier_unregister(struct mmu_
 {
 	BUG_ON(atomic_read(&mm->mm_count) <= 0);
 
+	spin_lock(&mm->mmu_notifier_mm->lock);
 	if (!hlist_unhashed(&mn->hlist)) {
-		/*
-		 * SRCU here will force exit_mmap to wait ->release to finish
-		 * before freeing the pages.
-		 */
 		int id;
 
-		id = srcu_read_lock(&srcu);
 		/*
-		 * exit_mmap will block in mmu_notifier_release to
-		 * guarantee ->release is called before freeing the
-		 * pages.
+		 * Ensure we synchronize up with __mmu_notifier_release().
 		 */
+		id = srcu_read_lock(&srcu);
+
+		hlist_del_rcu(&mn->hlist);
+		spin_unlock(&mm->mmu_notifier_mm->lock);
+
 		if (mn->ops->release)
 			mn->ops->release(mn, mm);
-		srcu_read_unlock(&srcu, id);
 
-		spin_lock(&mm->mmu_notifier_mm->lock);
-		hlist_del_rcu(&mn->hlist);
+		/*
+		 * Allow __mmu_notifier_release() to complete.
+		 */
+		srcu_read_unlock(&srcu, id);
+	} else
 		spin_unlock(&mm->mmu_notifier_mm->lock);
-	}
 
 	/*
-	 * Wait any running method to finish, of course including
-	 * ->release if it was run by mmu_notifier_relase instead of us.
+	 * Wait for any running method to finish, including ->release() if it
+	 * was run by __mmu_notifier_release() instead of us.
 	 */
 	synchronize_srcu(&srcu);
 
diff -druNp linux-libre-3.8-gnu1/mm/nommu.c linux-libre-3.8.13-gnu1/mm/nommu.c
--- linux-libre-3.8-gnu1/mm/nommu.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/nommu.c	2013-05-11 16:57:46.000000000 -0400
@@ -819,7 +819,7 @@ struct vm_area_struct *find_vma(struct m
 	struct vm_area_struct *vma;
 
 	/* check the cache first */
-	vma = mm->mmap_cache;
+	vma = ACCESS_ONCE(mm->mmap_cache);
 	if (vma && vma->vm_start <= addr && vma->vm_end > addr)
 		return vma;
 
diff -druNp linux-libre-3.8-gnu1/mm/page_io.c linux-libre-3.8.13-gnu1/mm/page_io.c
--- linux-libre-3.8-gnu1/mm/page_io.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/page_io.c	2013-05-11 16:57:46.000000000 -0400
@@ -214,6 +214,7 @@ int swap_writepage(struct page *page, st
 		kiocb.ki_left = PAGE_SIZE;
 		kiocb.ki_nbytes = PAGE_SIZE;
 
+		set_page_writeback(page);
 		unlock_page(page);
 		ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
 						&kiocb, &iov,
@@ -222,7 +223,23 @@ int swap_writepage(struct page *page, st
 		if (ret == PAGE_SIZE) {
 			count_vm_event(PSWPOUT);
 			ret = 0;
+		} else {
+			/*
+			 * In the case of swap-over-nfs, this can be a
+			 * temporary failure if the system has limited
+			 * memory for allocating transmit buffers.
+			 * Mark the page dirty and avoid
+			 * rotate_reclaimable_page but rate-limit the
+			 * messages but do not flag PageError like
+			 * the normal direct-to-bio case as it could
+			 * be temporary.
+			 */
+			set_page_dirty(page);
+			ClearPageReclaim(page);
+			pr_err_ratelimited("Write error on dio swapfile (%Lu)\n",
+				page_file_offset(page));
 		}
+		end_page_writeback(page);
 		return ret;
 	}
 
diff -druNp linux-libre-3.8-gnu1/mm/process_vm_access.c linux-libre-3.8.13-gnu1/mm/process_vm_access.c
--- linux-libre-3.8-gnu1/mm/process_vm_access.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/process_vm_access.c	2013-05-11 16:57:46.000000000 -0400
@@ -429,12 +429,6 @@ compat_process_vm_rw(compat_pid_t pid,
 	if (flags != 0)
 		return -EINVAL;
 
-	if (!access_ok(VERIFY_READ, lvec, liovcnt * sizeof(*lvec)))
-		goto out;
-
-	if (!access_ok(VERIFY_READ, rvec, riovcnt * sizeof(*rvec)))
-		goto out;
-
 	if (vm_write)
 		rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt,
 						  UIO_FASTIOV, iovstack_l,
@@ -459,8 +453,6 @@ free_iovecs:
 		kfree(iov_r);
 	if (iov_l != iovstack_l)
 		kfree(iov_l);
-
-out:
 	return rc;
 }
 
diff -druNp linux-libre-3.8-gnu1/mm/shmem.c linux-libre-3.8.13-gnu1/mm/shmem.c
--- linux-libre-3.8-gnu1/mm/shmem.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/mm/shmem.c	2013-05-11 16:57:46.000000000 -0400
@@ -2487,6 +2487,7 @@ static int shmem_remount_fs(struct super
 	unsigned long inodes;
 	int error = -EINVAL;
 
+	config.mpol = NULL;
 	if (shmem_parse_options(data, &config, true))
 		return error;
 
@@ -2511,8 +2512,13 @@ static int shmem_remount_fs(struct super
 	sbinfo->max_inodes  = config.max_inodes;
 	sbinfo->free_inodes = config.max_inodes - inodes;
 
-	mpol_put(sbinfo->mpol);
-	sbinfo->mpol        = config.mpol;	/* transfers initial ref */
+	/*
+	 * Preserve previous mempolicy unless mpol remount option was specified.
+	 */
+	if (config.mpol) {
+		mpol_put(sbinfo->mpol);
+		sbinfo->mpol = config.mpol;	/* transfers initial ref */
+	}
 out:
 	spin_unlock(&sbinfo->stat_lock);
 	return error;
diff -druNp linux-libre-3.8-gnu1/net/8021q/vlan.c linux-libre-3.8.13-gnu1/net/8021q/vlan.c
--- linux-libre-3.8-gnu1/net/8021q/vlan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/8021q/vlan.c	2013-05-11 16:57:46.000000000 -0400
@@ -86,13 +86,6 @@ void unregister_vlan_dev(struct net_devi
 
 	grp = &vlan_info->grp;
 
-	/* Take it out of our own structures, but be sure to interlock with
-	 * HW accelerating devices or SW vlan input packet processing if
-	 * VLAN is not 0 (leave it there for 802.1p).
-	 */
-	if (vlan_id)
-		vlan_vid_del(real_dev, vlan_id);
-
 	grp->nr_vlan_devs--;
 
 	if (vlan->flags & VLAN_FLAG_GVRP)
@@ -108,6 +101,13 @@ void unregister_vlan_dev(struct net_devi
 	if (grp->nr_vlan_devs == 0)
 		vlan_gvrp_uninit_applicant(real_dev);
 
+	/* Take it out of our own structures, but be sure to interlock with
+	 * HW accelerating devices or SW vlan input packet processing if
+	 * VLAN is not 0 (leave it there for 802.1p).
+	 */
+	if (vlan_id)
+		vlan_vid_del(real_dev, vlan_id);
+
 	/* Get rid of the vlan's reference to real_dev */
 	dev_put(real_dev);
 }
diff -druNp linux-libre-3.8-gnu1/net/atm/common.c linux-libre-3.8.13-gnu1/net/atm/common.c
--- linux-libre-3.8-gnu1/net/atm/common.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/atm/common.c	2013-05-11 16:57:46.000000000 -0400
@@ -532,6 +532,8 @@ int vcc_recvmsg(struct kiocb *iocb, stru
 	struct sk_buff *skb;
 	int copied, error = -EINVAL;
 
+	msg->msg_namelen = 0;
+
 	if (sock->state != SS_CONNECTED)
 		return -ENOTCONN;
 
diff -druNp linux-libre-3.8-gnu1/net/ax25/af_ax25.c linux-libre-3.8.13-gnu1/net/ax25/af_ax25.c
--- linux-libre-3.8-gnu1/net/ax25/af_ax25.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ax25/af_ax25.c	2013-05-11 16:57:46.000000000 -0400
@@ -1647,6 +1647,7 @@ static int ax25_recvmsg(struct kiocb *io
 		ax25_address src;
 		const unsigned char *mac = skb_mac_header(skb);
 
+		memset(sax, 0, sizeof(struct full_sockaddr_ax25));
 		ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
 				&digi, NULL, NULL);
 		sax->sax25_family = AF_AX25;
diff -druNp linux-libre-3.8-gnu1/net/batman-adv/bat_iv_ogm.c linux-libre-3.8.13-gnu1/net/batman-adv/bat_iv_ogm.c
--- linux-libre-3.8-gnu1/net/batman-adv/bat_iv_ogm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/batman-adv/bat_iv_ogm.c	2013-05-11 16:57:46.000000000 -0400
@@ -1298,7 +1298,8 @@ static int batadv_iv_ogm_receive(struct
 	batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
 
 	/* unpack the aggregated packets and process them one by one */
-	do {
+	while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
+					 batadv_ogm_packet->tt_num_changes)) {
 		tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
 
 		batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff,
@@ -1309,8 +1310,7 @@ static int batadv_iv_ogm_receive(struct
 
 		packet_pos = packet_buff + buff_pos;
 		batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
-	} while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
-					   batadv_ogm_packet->tt_num_changes));
+	}
 
 	kfree_skb(skb);
 	return NET_RX_SUCCESS;
diff -druNp linux-libre-3.8-gnu1/net/bluetooth/af_bluetooth.c linux-libre-3.8.13-gnu1/net/bluetooth/af_bluetooth.c
--- linux-libre-3.8-gnu1/net/bluetooth/af_bluetooth.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/bluetooth/af_bluetooth.c	2013-05-11 16:57:46.000000000 -0400
@@ -230,6 +230,8 @@ int bt_sock_recvmsg(struct kiocb *iocb,
 	if (flags & (MSG_OOB))
 		return -EOPNOTSUPP;
 
+	msg->msg_namelen = 0;
+
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb) {
 		if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb,
 		return err;
 	}
 
-	msg->msg_namelen = 0;
-
 	copied = skb->len;
 	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
diff -druNp linux-libre-3.8-gnu1/net/bluetooth/rfcomm/sock.c linux-libre-3.8.13-gnu1/net/bluetooth/rfcomm/sock.c
--- linux-libre-3.8-gnu1/net/bluetooth/rfcomm/sock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/bluetooth/rfcomm/sock.c	2013-05-11 16:57:46.000000000 -0400
@@ -610,6 +610,7 @@ static int rfcomm_sock_recvmsg(struct ki
 
 	if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 		rfcomm_dlc_accept(d);
+		msg->msg_namelen = 0;
 		return 0;
 	}
 
diff -druNp linux-libre-3.8-gnu1/net/bluetooth/sco.c linux-libre-3.8.13-gnu1/net/bluetooth/sco.c
--- linux-libre-3.8-gnu1/net/bluetooth/sco.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/bluetooth/sco.c	2013-05-11 16:57:46.000000000 -0400
@@ -361,6 +361,7 @@ static void __sco_sock_close(struct sock
 			sco_chan_del(sk, ECONNRESET);
 		break;
 
+	case BT_CONNECT2:
 	case BT_CONNECT:
 	case BT_DISCONN:
 		sco_chan_del(sk, ECONNRESET);
@@ -666,6 +667,7 @@ static int sco_sock_recvmsg(struct kiocb
 	    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
 		hci_conn_accept(pi->conn->hcon, 0);
 		sk->sk_state = BT_CONFIG;
+		msg->msg_namelen = 0;
 
 		release_sock(sk);
 		return 0;
diff -druNp linux-libre-3.8-gnu1/net/bridge/br_mdb.c linux-libre-3.8.13-gnu1/net/bridge/br_mdb.c
--- linux-libre-3.8-gnu1/net/bridge/br_mdb.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/bridge/br_mdb.c	2013-05-11 16:57:46.000000000 -0400
@@ -82,6 +82,7 @@ static int br_mdb_fill_info(struct sk_bu
 				port = p->port;
 				if (port) {
 					struct br_mdb_entry e;
+					memset(&e, 0, sizeof(e));
 					e.ifindex = port->dev->ifindex;
 					e.state = p->state;
 					if (p->addr.proto == htons(ETH_P_IP))
@@ -138,6 +139,7 @@ static int br_mdb_dump(struct sk_buff *s
 				break;
 
 			bpm = nlmsg_data(nlh);
+			memset(bpm, 0, sizeof(*bpm));
 			bpm->ifindex = dev->ifindex;
 			if (br_mdb_fill_info(skb, cb, dev) < 0)
 				goto out;
@@ -173,6 +175,7 @@ static int nlmsg_populate_mdb_fill(struc
 		return -EMSGSIZE;
 
 	bpm = nlmsg_data(nlh);
+	memset(bpm, 0, sizeof(*bpm));
 	bpm->family  = AF_BRIDGE;
 	bpm->ifindex = dev->ifindex;
 	nest = nla_nest_start(skb, MDBA_MDB);
@@ -230,6 +233,7 @@ void br_mdb_notify(struct net_device *de
 {
 	struct br_mdb_entry entry;
 
+	memset(&entry, 0, sizeof(entry));
 	entry.ifindex = port->dev->ifindex;
 	entry.addr.proto = group->proto;
 	entry.addr.u.ip4 = group->u.ip4;
diff -druNp linux-libre-3.8-gnu1/net/bridge/br_netlink.c linux-libre-3.8.13-gnu1/net/bridge/br_netlink.c
--- linux-libre-3.8-gnu1/net/bridge/br_netlink.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/bridge/br_netlink.c	2013-05-11 16:57:46.000000000 -0400
@@ -28,6 +28,7 @@ static inline size_t br_port_info_size(v
 		+ nla_total_size(1)	/* IFLA_BRPORT_MODE */
 		+ nla_total_size(1)	/* IFLA_BRPORT_GUARD */
 		+ nla_total_size(1)	/* IFLA_BRPORT_PROTECT */
+		+ nla_total_size(1)	/* IFLA_BRPORT_FAST_LEAVE */
 		+ 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/net/caif/caif_socket.c linux-libre-3.8.13-gnu1/net/caif/caif_socket.c
--- linux-libre-3.8-gnu1/net/caif/caif_socket.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/caif/caif_socket.c	2013-05-11 16:57:46.000000000 -0400
@@ -286,6 +286,8 @@ static int caif_seqpkt_recvmsg(struct ki
 	if (m->msg_flags&MSG_OOB)
 		goto read_error;
 
+	m->msg_namelen = 0;
+
 	skb = skb_recv_datagram(sk, flags, 0 , &ret);
 	if (!skb)
 		goto read_error;
diff -druNp linux-libre-3.8-gnu1/net/can/gw.c linux-libre-3.8.13-gnu1/net/can/gw.c
--- linux-libre-3.8-gnu1/net/can/gw.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/can/gw.c	2013-05-11 16:57:46.000000000 -0400
@@ -436,7 +436,7 @@ static int cgw_notifier(struct notifier_
 			if (gwj->src.dev == dev || gwj->dst.dev == dev) {
 				hlist_del(&gwj->list);
 				cgw_unregister_filter(gwj);
-				kfree(gwj);
+				kmem_cache_free(cgw_cache, gwj);
 			}
 		}
 	}
@@ -829,7 +829,7 @@ static void cgw_remove_all_jobs(void)
 	hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
 		hlist_del(&gwj->list);
 		cgw_unregister_filter(gwj);
-		kfree(gwj);
+		kmem_cache_free(cgw_cache, gwj);
 	}
 }
 
@@ -885,7 +885,7 @@ static int cgw_remove_job(struct sk_buff
 
 		hlist_del(&gwj->list);
 		cgw_unregister_filter(gwj);
-		kfree(gwj);
+		kmem_cache_free(cgw_cache, gwj);
 		err = 0;
 		break;
 	}
diff -druNp linux-libre-3.8-gnu1/net/core/dev_addr_lists.c linux-libre-3.8.13-gnu1/net/core/dev_addr_lists.c
--- linux-libre-3.8-gnu1/net/core/dev_addr_lists.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/dev_addr_lists.c	2013-05-11 16:57:46.000000000 -0400
@@ -38,7 +38,7 @@ static int __hw_addr_create_ex(struct ne
 	ha->type = addr_type;
 	ha->refcount = 1;
 	ha->global_use = global;
-	ha->synced = false;
+	ha->synced = 0;
 	list_add_tail_rcu(&ha->list, &list->list);
 	list->count++;
 
@@ -166,7 +166,7 @@ int __hw_addr_sync(struct netdev_hw_addr
 					    addr_len, ha->type);
 			if (err)
 				break;
-			ha->synced = true;
+			ha->synced++;
 			ha->refcount++;
 		} else if (ha->refcount == 1) {
 			__hw_addr_del(to_list, ha->addr, addr_len, ha->type);
@@ -187,7 +187,7 @@ void __hw_addr_unsync(struct netdev_hw_a
 		if (ha->synced) {
 			__hw_addr_del(to_list, ha->addr,
 				      addr_len, ha->type);
-			ha->synced = false;
+			ha->synced--;
 			__hw_addr_del(from_list, ha->addr,
 				      addr_len, ha->type);
 		}
diff -druNp linux-libre-3.8-gnu1/net/core/dev.c linux-libre-3.8.13-gnu1/net/core/dev.c
--- linux-libre-3.8-gnu1/net/core/dev.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/dev.c	2013-05-11 16:57:46.000000000 -0400
@@ -1591,7 +1591,6 @@ void net_enable_timestamp(void)
 		return;
 	}
 #endif
-	WARN_ON(in_interrupt());
 	static_key_slow_inc(&netstamp_needed);
 }
 EXPORT_SYMBOL(net_enable_timestamp);
@@ -1738,6 +1737,7 @@ int dev_forward_skb(struct net_device *d
 	skb->mark = 0;
 	secpath_reset(skb);
 	nf_reset(skb);
+	nf_reset_trace(skb);
 	return netif_rx(skb);
 }
 EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -2018,6 +2018,9 @@ static void skb_warn_bad_offload(const s
 	struct net_device *dev = skb->dev;
 	const char *driver = "";
 
+	if (!net_ratelimit())
+		return;
+
 	if (dev && dev->dev.parent)
 		driver = dev_driver_string(dev->dev.parent);
 
@@ -3277,6 +3280,7 @@ int netdev_rx_handler_register(struct ne
 	if (dev->rx_handler)
 		return -EBUSY;
 
+	/* Note: rx_handler_data must be set before rx_handler */
 	rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
 	rcu_assign_pointer(dev->rx_handler, rx_handler);
 
@@ -3297,6 +3301,11 @@ void netdev_rx_handler_unregister(struct
 
 	ASSERT_RTNL();
 	RCU_INIT_POINTER(dev->rx_handler, NULL);
+	/* a reader seeing a non NULL rx_handler in a rcu_read_lock()
+	 * section has a guarantee to see a non NULL rx_handler_data
+	 * as well.
+	 */
+	synchronize_net();
 	RCU_INIT_POINTER(dev->rx_handler_data, NULL);
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
@@ -3419,6 +3428,7 @@ ncls:
 		}
 		switch (rx_handler(&skb)) {
 		case RX_HANDLER_CONSUMED:
+			ret = NET_RX_SUCCESS;
 			goto unlock;
 		case RX_HANDLER_ANOTHER:
 			goto another_round;
diff -druNp linux-libre-3.8-gnu1/net/core/dst.c linux-libre-3.8.13-gnu1/net/core/dst.c
--- linux-libre-3.8-gnu1/net/core/dst.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/dst.c	2013-05-11 16:57:46.000000000 -0400
@@ -179,6 +179,7 @@ void *dst_alloc(struct dst_ops *ops, str
 	dst_init_metrics(dst, dst_default_metrics, true);
 	dst->expires = 0UL;
 	dst->path = dst;
+	dst->from = NULL;
 #ifdef CONFIG_XFRM
 	dst->xfrm = NULL;
 #endif
diff -druNp linux-libre-3.8-gnu1/net/core/flow.c linux-libre-3.8.13-gnu1/net/core/flow.c
--- linux-libre-3.8-gnu1/net/core/flow.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/flow.c	2013-05-11 16:57:46.000000000 -0400
@@ -329,7 +329,7 @@ static void flow_cache_flush_per_cpu(voi
 	struct flow_flush_info *info = data;
 	struct tasklet_struct *tasklet;
 
-	tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet);
+	tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet;
 	tasklet->data = (unsigned long)info;
 	tasklet_schedule(tasklet);
 }
diff -druNp linux-libre-3.8-gnu1/net/core/rtnetlink.c linux-libre-3.8.13-gnu1/net/core/rtnetlink.c
--- linux-libre-3.8-gnu1/net/core/rtnetlink.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/rtnetlink.c	2013-05-11 16:57:46.000000000 -0400
@@ -976,6 +976,7 @@ static int rtnl_fill_ifinfo(struct sk_bu
 			 * report anything.
 			 */
 			ivi.spoofchk = -1;
+			memset(ivi.mac, 0, sizeof(ivi.mac));
 			if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
 				break;
 			vf_mac.vf =
@@ -1067,7 +1068,7 @@ static int rtnl_dump_ifinfo(struct sk_bu
 	rcu_read_lock();
 	cb->seq = net->dev_base_seq;
 
-	if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+	if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
 			ifla_policy) >= 0) {
 
 		if (tb[IFLA_EXT_MASK])
@@ -1923,7 +1924,7 @@ static u16 rtnl_calcit(struct sk_buff *s
 	u32 ext_filter_mask = 0;
 	u16 min_ifinfo_dump_size = 0;
 
-	if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+	if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
 			ifla_policy) >= 0) {
 		if (tb[IFLA_EXT_MASK])
 			ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
@@ -2538,7 +2539,7 @@ static int rtnetlink_rcv_msg(struct sk_b
 		struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);
 
 		while (RTA_OK(attr, attrlen)) {
-			unsigned int flavor = attr->rta_type;
+			unsigned int flavor = attr->rta_type & NLA_TYPE_MASK;
 			if (flavor) {
 				if (flavor > rta_max[sz_idx])
 					return -EINVAL;
diff -druNp linux-libre-3.8-gnu1/net/core/scm.c linux-libre-3.8.13-gnu1/net/core/scm.c
--- linux-libre-3.8-gnu1/net/core/scm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/scm.c	2013-05-11 16:57:46.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/security.h>
+#include <linux/pid_namespace.h>
 #include <linux/pid.h>
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
@@ -52,7 +53,8 @@ static __inline__ int scm_check_creds(st
 	if (!uid_valid(uid) || !gid_valid(gid))
 		return -EINVAL;
 
-	if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) &&
+	if ((creds->pid == task_tgid_vnr(current) ||
+	     ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) &&
 	    ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||
 	      uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
 	    ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) ||
diff -druNp linux-libre-3.8-gnu1/net/core/sock_diag.c linux-libre-3.8.13-gnu1/net/core/sock_diag.c
--- linux-libre-3.8-gnu1/net/core/sock_diag.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/core/sock_diag.c	2013-05-11 16:57:46.000000000 -0400
@@ -121,6 +121,9 @@ static int __sock_diag_rcv_msg(struct sk
 	if (nlmsg_len(nlh) < sizeof(*req))
 		return -EINVAL;
 
+	if (req->sdiag_family >= AF_MAX)
+		return -EINVAL;
+
 	hndl = sock_diag_lock_handler(req->sdiag_family);
 	if (hndl == NULL)
 		err = -ENOENT;
diff -druNp linux-libre-3.8-gnu1/net/dcb/dcbnl.c linux-libre-3.8.13-gnu1/net/dcb/dcbnl.c
--- linux-libre-3.8-gnu1/net/dcb/dcbnl.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/dcb/dcbnl.c	2013-05-11 16:57:46.000000000 -0400
@@ -284,6 +284,7 @@ static int dcbnl_getperm_hwaddr(struct n
 	if (!netdev->dcbnl_ops->getpermhwaddr)
 		return -EOPNOTSUPP;
 
+	memset(perm_addr, 0, sizeof(perm_addr));
 	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
 
 	return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr);
@@ -1042,6 +1043,7 @@ static int dcbnl_ieee_fill(struct sk_buf
 
 	if (ops->ieee_getets) {
 		struct ieee_ets ets;
+		memset(&ets, 0, sizeof(ets));
 		err = ops->ieee_getets(netdev, &ets);
 		if (!err &&
 		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
@@ -1050,6 +1052,7 @@ static int dcbnl_ieee_fill(struct sk_buf
 
 	if (ops->ieee_getmaxrate) {
 		struct ieee_maxrate maxrate;
+		memset(&maxrate, 0, sizeof(maxrate));
 		err = ops->ieee_getmaxrate(netdev, &maxrate);
 		if (!err) {
 			err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
@@ -1061,6 +1064,7 @@ static int dcbnl_ieee_fill(struct sk_buf
 
 	if (ops->ieee_getpfc) {
 		struct ieee_pfc pfc;
+		memset(&pfc, 0, sizeof(pfc));
 		err = ops->ieee_getpfc(netdev, &pfc);
 		if (!err &&
 		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
@@ -1094,6 +1098,7 @@ static int dcbnl_ieee_fill(struct sk_buf
 	/* get peer info if available */
 	if (ops->ieee_peer_getets) {
 		struct ieee_ets ets;
+		memset(&ets, 0, sizeof(ets));
 		err = ops->ieee_peer_getets(netdev, &ets);
 		if (!err &&
 		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
@@ -1102,6 +1107,7 @@ static int dcbnl_ieee_fill(struct sk_buf
 
 	if (ops->ieee_peer_getpfc) {
 		struct ieee_pfc pfc;
+		memset(&pfc, 0, sizeof(pfc));
 		err = ops->ieee_peer_getpfc(netdev, &pfc);
 		if (!err &&
 		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
@@ -1280,6 +1286,7 @@ static int dcbnl_cee_fill(struct sk_buff
 	/* peer info if available */
 	if (ops->cee_peer_getpg) {
 		struct cee_pg pg;
+		memset(&pg, 0, sizeof(pg));
 		err = ops->cee_peer_getpg(netdev, &pg);
 		if (!err &&
 		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
@@ -1288,6 +1295,7 @@ static int dcbnl_cee_fill(struct sk_buff
 
 	if (ops->cee_peer_getpfc) {
 		struct cee_pfc pfc;
+		memset(&pfc, 0, sizeof(pfc));
 		err = ops->cee_peer_getpfc(netdev, &pfc);
 		if (!err &&
 		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
diff -druNp linux-libre-3.8-gnu1/net/ieee802154/6lowpan.c linux-libre-3.8.13-gnu1/net/ieee802154/6lowpan.c
--- linux-libre-3.8-gnu1/net/ieee802154/6lowpan.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ieee802154/6lowpan.c	2013-05-11 16:57:46.000000000 -0400
@@ -1234,7 +1234,7 @@ static inline int __init lowpan_netlink_
 	return rtnl_link_register(&lowpan_link_ops);
 }
 
-static inline void __init lowpan_netlink_fini(void)
+static inline void lowpan_netlink_fini(void)
 {
 	rtnl_link_unregister(&lowpan_link_ops);
 }
diff -druNp linux-libre-3.8-gnu1/net/ieee802154/6lowpan.h linux-libre-3.8.13-gnu1/net/ieee802154/6lowpan.h
--- linux-libre-3.8-gnu1/net/ieee802154/6lowpan.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ieee802154/6lowpan.h	2013-05-11 16:57:46.000000000 -0400
@@ -84,7 +84,7 @@
 	(memcmp(addr1, addr2, length >> 3) == 0)
 
 /* local link, i.e. FE80::/10 */
-#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE)
+#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80))
 
 /*
  * check whether we can compress the IID to 16 bits,
diff -druNp linux-libre-3.8-gnu1/net/ipv4/af_inet.c linux-libre-3.8.13-gnu1/net/ipv4/af_inet.c
--- linux-libre-3.8-gnu1/net/ipv4/af_inet.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/af_inet.c	2013-05-11 16:57:46.000000000 -0400
@@ -248,8 +248,12 @@ EXPORT_SYMBOL(inet_listen);
 u32 inet_ehash_secret __read_mostly;
 EXPORT_SYMBOL(inet_ehash_secret);
 
+u32 ipv6_hash_secret __read_mostly;
+EXPORT_SYMBOL(ipv6_hash_secret);
+
 /*
- * inet_ehash_secret must be set exactly once
+ * inet_ehash_secret must be set exactly once, and to a non nul value
+ * ipv6_hash_secret must be set exactly once.
  */
 void build_ehash_secret(void)
 {
@@ -259,7 +263,8 @@ void build_ehash_secret(void)
 		get_random_bytes(&rnd, sizeof(rnd));
 	} while (rnd == 0);
 
-	cmpxchg(&inet_ehash_secret, 0, rnd);
+	if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0)
+		get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret));
 }
 EXPORT_SYMBOL(build_ehash_secret);
 
@@ -1590,7 +1595,7 @@ static const struct net_offload udp_offl
 
 static const struct net_protocol icmp_protocol = {
 	.handler =	icmp_rcv,
-	.err_handler =	ping_err,
+	.err_handler =	icmp_err,
 	.no_policy =	1,
 	.netns_ok =	1,
 };
diff -druNp linux-libre-3.8-gnu1/net/ipv4/esp4.c linux-libre-3.8.13-gnu1/net/ipv4/esp4.c
--- linux-libre-3.8-gnu1/net/ipv4/esp4.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/esp4.c	2013-05-11 16:57:46.000000000 -0400
@@ -139,8 +139,6 @@ static int esp_output(struct xfrm_state
 
 	/* skb is pure payload to encrypt */
 
-	err = -ENOMEM;
-
 	esp = x->data;
 	aead = esp->aead;
 	alen = crypto_aead_authsize(aead);
@@ -176,8 +174,10 @@ static int esp_output(struct xfrm_state
 	}
 
 	tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
-	if (!tmp)
+	if (!tmp) {
+		err = -ENOMEM;
 		goto error;
+	}
 
 	seqhi = esp_tmp_seqhi(tmp);
 	iv = esp_tmp_iv(aead, tmp, seqhilen);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/icmp.c linux-libre-3.8.13-gnu1/net/ipv4/icmp.c
--- linux-libre-3.8-gnu1/net/ipv4/icmp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/icmp.c	2013-05-11 16:57:46.000000000 -0400
@@ -934,6 +934,29 @@ error:
 	goto drop;
 }
 
+void icmp_err(struct sk_buff *skb, u32 info)
+{
+	struct iphdr *iph = (struct iphdr *)skb->data;
+	struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
+	int type = icmp_hdr(skb)->type;
+	int code = icmp_hdr(skb)->code;
+	struct net *net = dev_net(skb->dev);
+
+	/*
+	 * Use ping_err to handle all icmp errors except those
+	 * triggered by ICMP_ECHOREPLY which sent from kernel.
+	 */
+	if (icmph->type != ICMP_ECHOREPLY) {
+		ping_err(skb, info);
+		return;
+	}
+
+	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
+		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ICMP, 0);
+	else if (type == ICMP_REDIRECT)
+		ipv4_redirect(skb, net, 0, 0, IPPROTO_ICMP, 0);
+}
+
 /*
  *	This table is the definition of how we handle ICMP.
  */
diff -druNp linux-libre-3.8-gnu1/net/ipv4/inet_fragment.c linux-libre-3.8.13-gnu1/net/ipv4/inet_fragment.c
--- linux-libre-3.8-gnu1/net/ipv4/inet_fragment.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/inet_fragment.c	2013-05-11 16:57:46.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
 
+#include <net/sock.h>
 #include <net/inet_frag.h>
 
 static void inet_frag_secret_rebuild(unsigned long dummy)
@@ -276,6 +277,7 @@ struct inet_frag_queue *inet_frag_find(s
 {
 	struct inet_frag_queue *q;
 	struct hlist_node *n;
+	int depth = 0;
 
 	hlist_for_each_entry(q, n, &f->hash[hash], list) {
 		if (q->net == nf && f->match(q, key)) {
@@ -283,9 +285,25 @@ struct inet_frag_queue *inet_frag_find(s
 			read_unlock(&f->lock);
 			return q;
 		}
+		depth++;
 	}
 	read_unlock(&f->lock);
 
-	return inet_frag_create(nf, f, key);
+	if (depth <= INETFRAGS_MAXDEPTH)
+		return inet_frag_create(nf, f, key);
+	else
+		return ERR_PTR(-ENOBUFS);
 }
 EXPORT_SYMBOL(inet_frag_find);
+
+void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
+				   const char *prefix)
+{
+	static const char msg[] = "inet_frag_find: Fragment hash bucket"
+		" list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
+		". Dropping fragment.\n";
+
+	if (PTR_ERR(q) == -ENOBUFS)
+		LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
+}
+EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/ip_fragment.c linux-libre-3.8.13-gnu1/net/ipv4/ip_fragment.c
--- linux-libre-3.8-gnu1/net/ipv4/ip_fragment.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/ip_fragment.c	2013-05-11 16:57:46.000000000 -0400
@@ -255,8 +255,7 @@ static void ip_expire(unsigned long arg)
 		if (!head->dev)
 			goto out_rcu_unlock;
 
-		/* skb dst is stale, drop it, and perform route lookup again */
-		skb_dst_drop(head);
+		/* skb has no dst, perform route lookup again */
 		iph = ip_hdr(head);
 		err = ip_route_input_noref(head, iph->daddr, iph->saddr,
 					   iph->tos, head->dev);
@@ -299,14 +298,11 @@ static inline struct ipq *ip_find(struct
 	hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
 
 	q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
-	if (q == NULL)
-		goto out_nomem;
-
+	if (IS_ERR_OR_NULL(q)) {
+		inet_frag_maybe_warn_overflow(q, pr_fmt());
+		return NULL;
+	}
 	return container_of(q, struct ipq, q);
-
-out_nomem:
-	LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n"));
-	return NULL;
 }
 
 /* Is the fragment too far ahead to be part of ipq? */
@@ -528,8 +524,16 @@ found:
 		qp->q.max_size = skb->len + ihl;
 
 	if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
-	    qp->q.meat == qp->q.len)
-		return ip_frag_reasm(qp, prev, dev);
+	    qp->q.meat == qp->q.len) {
+		unsigned long orefdst = skb->_skb_refdst;
+
+		skb->_skb_refdst = 0UL;
+		err = ip_frag_reasm(qp, prev, dev);
+		skb->_skb_refdst = orefdst;
+		return err;
+	}
+
+	skb_dst_drop(skb);
 
 	write_lock(&ip4_frags.lock);
 	list_move_tail(&qp->q.lru_list, &qp->q.net->lru_list);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/ip_gre.c linux-libre-3.8.13-gnu1/net/ipv4/ip_gre.c
--- linux-libre-3.8-gnu1/net/ipv4/ip_gre.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/ip_gre.c	2013-05-11 16:57:46.000000000 -0400
@@ -761,10 +761,7 @@ static netdev_tx_t ipgre_tunnel_xmit(str
 
 	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
 		gre_hlen = 0;
-		if (skb->protocol == htons(ETH_P_IP))
-			tiph = (const struct iphdr *)skb->data;
-		else
-			tiph = &tunnel->parms.iph;
+		tiph = (const struct iphdr *)skb->data;
 	} else {
 		gre_hlen = tunnel->hlen;
 		tiph = &tunnel->parms.iph;
diff -druNp linux-libre-3.8-gnu1/net/ipv4/ip_options.c linux-libre-3.8.13-gnu1/net/ipv4/ip_options.c
--- linux-libre-3.8-gnu1/net/ipv4/ip_options.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/ip_options.c	2013-05-11 16:57:46.000000000 -0400
@@ -370,7 +370,6 @@ int ip_options_compile(struct net *net,
 				}
 				switch (optptr[3]&0xF) {
 				      case IPOPT_TS_TSONLY:
-					opt->ts = optptr - iph;
 					if (skb)
 						timeptr = &optptr[optptr[2]-1];
 					opt->ts_needtime = 1;
@@ -381,7 +380,6 @@ int ip_options_compile(struct net *net,
 						pp_ptr = optptr + 2;
 						goto error;
 					}
-					opt->ts = optptr - iph;
 					if (rt)  {
 						spec_dst_fill(&spec_dst, skb);
 						memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
@@ -396,7 +394,6 @@ int ip_options_compile(struct net *net,
 						pp_ptr = optptr + 2;
 						goto error;
 					}
-					opt->ts = optptr - iph;
 					{
 						__be32 addr;
 						memcpy(&addr, &optptr[optptr[2]-1], 4);
@@ -429,12 +426,12 @@ int ip_options_compile(struct net *net,
 					pp_ptr = optptr + 3;
 					goto error;
 				}
-				opt->ts = optptr - iph;
 				if (skb) {
 					optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
 					opt->is_changed = 1;
 				}
 			}
+			opt->ts = optptr - iph;
 			break;
 		      case IPOPT_RA:
 			if (optlen < 4) {
diff -druNp linux-libre-3.8-gnu1/net/ipv4/netfilter/ipt_rpfilter.c linux-libre-3.8.13-gnu1/net/ipv4/netfilter/ipt_rpfilter.c
--- linux-libre-3.8-gnu1/net/ipv4/netfilter/ipt_rpfilter.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/netfilter/ipt_rpfilter.c	2013-05-11 16:57:46.000000000 -0400
@@ -66,6 +66,12 @@ static bool rpfilter_lookup_reverse(stru
 	return dev_match;
 }
 
+static bool rpfilter_is_local(const struct sk_buff *skb)
+{
+	const struct rtable *rt = skb_rtable(skb);
+	return rt && (rt->rt_flags & RTCF_LOCAL);
+}
+
 static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_rpfilter_info *info;
@@ -76,7 +82,7 @@ static bool rpfilter_mt(const struct sk_
 	info = par->matchinfo;
 	invert = info->flags & XT_RPFILTER_INVERT;
 
-	if (par->in->flags & IFF_LOOPBACK)
+	if (rpfilter_is_local(skb))
 		return true ^ invert;
 
 	iph = ip_hdr(skb);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/ping.c linux-libre-3.8.13-gnu1/net/ipv4/ping.c
--- linux-libre-3.8-gnu1/net/ipv4/ping.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/ping.c	2013-05-11 16:57:46.000000000 -0400
@@ -322,8 +322,8 @@ void ping_err(struct sk_buff *skb, u32 i
 	struct iphdr *iph = (struct iphdr *)skb->data;
 	struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
 	struct inet_sock *inet_sock;
-	int type = icmph->type;
-	int code = icmph->code;
+	int type = icmp_hdr(skb)->type;
+	int code = icmp_hdr(skb)->code;
 	struct net *net = dev_net(skb->dev);
 	struct sock *sk;
 	int harderr;
diff -druNp linux-libre-3.8-gnu1/net/ipv4/syncookies.c linux-libre-3.8.13-gnu1/net/ipv4/syncookies.c
--- linux-libre-3.8-gnu1/net/ipv4/syncookies.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/syncookies.c	2013-05-11 16:57:46.000000000 -0400
@@ -348,8 +348,8 @@ struct sock *cookie_v4_check(struct sock
 	 * hasn't changed since we received the original syn, but I see
 	 * no easy way to do this.
 	 */
-	flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
-			   RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+	flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark,
+			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
 			   inet_sk_flowi_flags(sk),
 			   (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
 			   ireq->loc_addr, th->source, th->dest);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/tcp.c linux-libre-3.8.13-gnu1/net/ipv4/tcp.c
--- linux-libre-3.8-gnu1/net/ipv4/tcp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/tcp.c	2013-05-11 16:57:46.000000000 -0400
@@ -773,7 +773,7 @@ struct sk_buff *sk_stream_alloc_skb(stru
 			 * Make sure that we have exactly size bytes
 			 * available to the caller, no more, no less.
 			 */
-			skb->avail_size = size;
+			skb->reserved_tailroom = skb->end - skb->tail - size;
 			return skb;
 		}
 		__kfree_skb(skb);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/tcp_input.c linux-libre-3.8.13-gnu1/net/ipv4/tcp_input.c
--- linux-libre-3.8-gnu1/net/ipv4/tcp_input.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/tcp_input.c	2013-05-11 16:57:46.000000000 -0400
@@ -116,6 +116,7 @@ int sysctl_tcp_early_retrans __read_most
 #define FLAG_DSACKING_ACK	0x800 /* SACK blocks contained D-SACK info */
 #define FLAG_NONHEAD_RETRANS_ACKED	0x1000 /* Non-head rexmitted data was ACKed */
 #define FLAG_SACK_RENEGING	0x2000 /* snd_una advanced to a sacked seq */
+#define FLAG_UPDATE_TS_RECENT	0x4000 /* tcp_replace_ts_recent() */
 
 #define FLAG_ACKED		(FLAG_DATA_ACKED|FLAG_SYN_ACKED)
 #define FLAG_NOT_DUP		(FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
@@ -2064,11 +2065,8 @@ void tcp_enter_loss(struct sock *sk, int
 	if (tcp_is_reno(tp))
 		tcp_reset_reno_sack(tp);
 
-	if (!how) {
-		/* Push undo marker, if it was plain RTO and nothing
-		 * was retransmitted. */
-		tp->undo_marker = tp->snd_una;
-	} else {
+	tp->undo_marker = tp->snd_una;
+	if (how) {
 		tp->sacked_out = 0;
 		tp->fackets_out = 0;
 	}
@@ -3575,6 +3573,27 @@ static void tcp_send_challenge_ack(struc
 	}
 }
 
+static void tcp_store_ts_recent(struct tcp_sock *tp)
+{
+	tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
+	tp->rx_opt.ts_recent_stamp = get_seconds();
+}
+
+static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
+{
+	if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
+		/* PAWS bug workaround wrt. ACK frames, the PAWS discard
+		 * extra check below makes sure this can only happen
+		 * for pure ACK frames.  -DaveM
+		 *
+		 * Not only, also it occurs for expired timestamps.
+		 */
+
+		if (tcp_paws_check(&tp->rx_opt, 0))
+			tcp_store_ts_recent(tp);
+	}
+}
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 {
@@ -3627,6 +3646,12 @@ static int tcp_ack(struct sock *sk, cons
 	prior_fackets = tp->fackets_out;
 	prior_in_flight = tcp_packets_in_flight(tp);
 
+	/* ts_recent update must be made after we are sure that the packet
+	 * is in window.
+	 */
+	if (flag & FLAG_UPDATE_TS_RECENT)
+		tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
 	if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
 		/* Window is constant, pure forward advance.
 		 * No more checks are required.
@@ -3943,27 +3968,6 @@ const u8 *tcp_parse_md5sig_option(const
 EXPORT_SYMBOL(tcp_parse_md5sig_option);
 #endif
 
-static inline void tcp_store_ts_recent(struct tcp_sock *tp)
-{
-	tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
-	tp->rx_opt.ts_recent_stamp = get_seconds();
-}
-
-static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
-{
-	if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
-		/* PAWS bug workaround wrt. ACK frames, the PAWS discard
-		 * extra check below makes sure this can only happen
-		 * for pure ACK frames.  -DaveM
-		 *
-		 * Not only, also it occurs for expired timestamps.
-		 */
-
-		if (tcp_paws_check(&tp->rx_opt, 0))
-			tcp_store_ts_recent(tp);
-	}
-}
-
 /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
  *
  * It is not fatal. If this ACK does _not_ change critical state (seqs, window)
@@ -5498,6 +5502,9 @@ int tcp_rcv_established(struct sock *sk,
 				if (tcp_checksum_complete_user(sk, skb))
 					goto csum_error;
 
+				if ((int)skb->truesize > sk->sk_forward_alloc)
+					goto step5;
+
 				/* Predicted packet is in window by definition.
 				 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
 				 * Hence, check seq<=rcv_wup reduces to:
@@ -5509,9 +5516,6 @@ int tcp_rcv_established(struct sock *sk,
 
 				tcp_rcv_rtt_measure_ts(sk, skb);
 
-				if ((int)skb->truesize > sk->sk_forward_alloc)
-					goto step5;
-
 				NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS);
 
 				/* Bulk data transfer: receiver */
@@ -5559,14 +5563,9 @@ slow_path:
 		return 0;
 
 step5:
-	if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+	if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
 		goto discard;
 
-	/* ts_recent update must be made after we are sure that the packet
-	 * is in window.
-	 */
-	tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
 	tcp_rcv_rtt_measure_ts(sk, skb);
 
 	/* Process urgent data. */
@@ -6000,7 +5999,8 @@ int tcp_rcv_state_process(struct sock *s
 
 	/* step 5: check the ACK field */
 	if (true) {
-		int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
+		int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
+						  FLAG_UPDATE_TS_RECENT) > 0;
 
 		switch (sk->sk_state) {
 		case TCP_SYN_RECV:
@@ -6151,11 +6151,6 @@ int tcp_rcv_state_process(struct sock *s
 		}
 	}
 
-	/* ts_recent update must be made after we are sure that the packet
-	 * is in window.
-	 */
-	tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
 	/* step 6: check the URG bit */
 	tcp_urg(sk, skb, th);
 
diff -druNp linux-libre-3.8-gnu1/net/ipv4/tcp_ipv4.c linux-libre-3.8.13-gnu1/net/ipv4/tcp_ipv4.c
--- linux-libre-3.8-gnu1/net/ipv4/tcp_ipv4.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/tcp_ipv4.c	2013-05-11 16:57:46.000000000 -0400
@@ -274,13 +274,6 @@ static void tcp_v4_mtu_reduced(struct so
 	struct inet_sock *inet = inet_sk(sk);
 	u32 mtu = tcp_sk(sk)->mtu_info;
 
-	/* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
-	 * send out by Linux are always <576bytes so they should go through
-	 * unfragmented).
-	 */
-	if (sk->sk_state == TCP_LISTEN)
-		return;
-
 	dst = inet_csk_update_pmtu(sk, mtu);
 	if (!dst)
 		return;
@@ -408,6 +401,13 @@ void tcp_v4_err(struct sk_buff *icmp_skb
 			goto out;
 
 		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
+			/* We are not interested in TCP_LISTEN and open_requests
+			 * (SYN-ACKs send out by Linux are always <576bytes so
+			 * they should go through unfragmented).
+			 */
+			if (sk->sk_state == TCP_LISTEN)
+				goto out;
+
 			tp->mtu_info = info;
 			if (!sock_owned_by_user(sk)) {
 				tcp_v4_mtu_reduced(sk);
diff -druNp linux-libre-3.8-gnu1/net/ipv4/tcp_output.c linux-libre-3.8.13-gnu1/net/ipv4/tcp_output.c
--- linux-libre-3.8-gnu1/net/ipv4/tcp_output.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv4/tcp_output.c	2013-05-11 16:57:46.000000000 -0400
@@ -1298,7 +1298,6 @@ static void __pskb_trim_head(struct sk_b
 	eat = min_t(int, len, skb_headlen(skb));
 	if (eat) {
 		__skb_pull(skb, eat);
-		skb->avail_size -= eat;
 		len -= eat;
 		if (!len)
 			return;
@@ -1351,8 +1350,8 @@ int tcp_trim_head(struct sock *sk, struc
 	return 0;
 }
 
-/* Calculate MSS. Not accounting for SACKs here.  */
-int tcp_mtu_to_mss(struct sock *sk, int pmtu)
+/* Calculate MSS not accounting any TCP options.  */
+static inline int __tcp_mtu_to_mss(struct sock *sk, int pmtu)
 {
 	const struct tcp_sock *tp = tcp_sk(sk);
 	const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -1381,13 +1380,17 @@ int tcp_mtu_to_mss(struct sock *sk, int
 	/* Then reserve room for full set of TCP options and 8 bytes of data */
 	if (mss_now < 48)
 		mss_now = 48;
-
-	/* Now subtract TCP options size, not including SACKs */
-	mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
-
 	return mss_now;
 }
 
+/* Calculate MSS. Not accounting for SACKs here.  */
+int tcp_mtu_to_mss(struct sock *sk, int pmtu)
+{
+	/* Subtract TCP options size, not including SACKs */
+	return __tcp_mtu_to_mss(sk, pmtu) -
+	       (tcp_sk(sk)->tcp_header_len - sizeof(struct tcphdr));
+}
+
 /* Inverse of above */
 int tcp_mss_to_mtu(struct sock *sk, int mss)
 {
@@ -1806,8 +1809,11 @@ static bool tcp_tso_should_defer(struct
 			goto send_now;
 	}
 
-	/* Ok, it looks like it is advisable to defer.  */
-	tp->tso_deferred = 1 | (jiffies << 1);
+	/* Ok, it looks like it is advisable to defer.
+	 * Do not rearm the timer if already set to not break TCP ACK clocking.
+	 */
+	if (!tp->tso_deferred)
+		tp->tso_deferred = 1 | (jiffies << 1);
 
 	return true;
 
@@ -2382,8 +2388,12 @@ int __tcp_retransmit_skb(struct sock *sk
 	 */
 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
-	/* make sure skb->data is aligned on arches that require it */
-	if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
+	/* make sure skb->data is aligned on arches that require it
+	 * and check if ack-trimming & collapsing extended the headroom
+	 * beyond what csum_start can cover.
+	 */
+	if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
+		     skb_headroom(skb) >= 0xFFFF)) {
 		struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
 						   GFP_ATOMIC);
 		return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
@@ -2930,7 +2940,7 @@ static int tcp_send_syn_data(struct sock
 	 */
 	if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < tp->rx_opt.mss_clamp)
 		tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
-	space = tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
+	space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
 		MAX_TCP_OPTION_SPACE;
 
 	syn_data = skb_copy_expand(syn, skb_headroom(syn), space,
diff -druNp linux-libre-3.8-gnu1/net/ipv6/addrconf.c linux-libre-3.8.13-gnu1/net/ipv6/addrconf.c
--- linux-libre-3.8-gnu1/net/ipv6/addrconf.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/addrconf.c	2013-05-11 16:57:46.000000000 -0400
@@ -2525,6 +2525,9 @@ static void sit_add_v4_addrs(struct inet
 static void init_loopback(struct net_device *dev)
 {
 	struct inet6_dev  *idev;
+	struct net_device *sp_dev;
+	struct inet6_ifaddr *sp_ifa;
+	struct rt6_info *sp_rt;
 
 	/* ::1 */
 
@@ -2536,6 +2539,30 @@ static void init_loopback(struct net_dev
 	}
 
 	add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
+
+	/* Add routes to other interface's IPv6 addresses */
+	for_each_netdev(dev_net(dev), sp_dev) {
+		if (!strcmp(sp_dev->name, dev->name))
+			continue;
+
+		idev = __in6_dev_get(sp_dev);
+		if (!idev)
+			continue;
+
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
+
+			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
+				continue;
+
+			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+
+			/* Failure cases are ignored */
+			if (!IS_ERR(sp_rt))
+				ip6_ins_rt(sp_rt);
+		}
+		read_unlock_bh(&idev->lock);
+	}
 }
 
 static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
@@ -4787,26 +4814,20 @@ static void addrconf_sysctl_unregister(s
 
 static int __net_init addrconf_init_net(struct net *net)
 {
-	int err;
+	int err = -ENOMEM;
 	struct ipv6_devconf *all, *dflt;
 
-	err = -ENOMEM;
-	all = &ipv6_devconf;
-	dflt = &ipv6_devconf_dflt;
+	all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
+	if (all == NULL)
+		goto err_alloc_all;
 
-	if (!net_eq(net, &init_net)) {
-		all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL);
-		if (all == NULL)
-			goto err_alloc_all;
+	dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
+	if (dflt == NULL)
+		goto err_alloc_dflt;
 
-		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
-		if (dflt == NULL)
-			goto err_alloc_dflt;
-	} else {
-		/* these will be inherited by all namespaces */
-		dflt->autoconf = ipv6_defaults.autoconf;
-		dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
-	}
+	/* these will be inherited by all namespaces */
+	dflt->autoconf = ipv6_defaults.autoconf;
+	dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
 
 	net->ipv6.devconf_all = all;
 	net->ipv6.devconf_dflt = dflt;
diff -druNp linux-libre-3.8-gnu1/net/ipv6/ip6_input.c linux-libre-3.8.13-gnu1/net/ipv6/ip6_input.c
--- linux-libre-3.8-gnu1/net/ipv6/ip6_input.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/ip6_input.c	2013-05-11 16:57:46.000000000 -0400
@@ -118,6 +118,27 @@ int ipv6_rcv(struct sk_buff *skb, struct
 	    ipv6_addr_loopback(&hdr->daddr))
 		goto err;
 
+	/* RFC4291 Errata ID: 3480
+	 * Interface-Local scope spans only a single interface on a
+	 * node and is useful only for loopback transmission of
+	 * multicast.  Packets with interface-local scope received
+	 * from another node must be discarded.
+	 */
+	if (!(skb->pkt_type == PACKET_LOOPBACK ||
+	      dev->flags & IFF_LOOPBACK) &&
+	    ipv6_addr_is_multicast(&hdr->daddr) &&
+	    IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
+		goto err;
+
+	/* RFC4291 2.7
+	 * Nodes must not originate a packet to a multicast address whose scope
+	 * field contains the reserved value 0; if such a packet is received, it
+	 * must be silently dropped.
+	 */
+	if (ipv6_addr_is_multicast(&hdr->daddr) &&
+	    IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
+		goto err;
+
 	/*
 	 * RFC4291 2.7
 	 * Multicast addresses must not be used as source addresses in IPv6
@@ -270,7 +291,8 @@ int ip6_mc_input(struct sk_buff *skb)
 	 *      IPv6 multicast router mode is now supported ;)
 	 */
 	if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
-	    !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) &&
+	    !(ipv6_addr_type(&hdr->daddr) &
+	      (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
 	    likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
 		/*
 		 * Okay, we try to forward - split and duplicate
diff -druNp linux-libre-3.8-gnu1/net/ipv6/netfilter/ip6t_NPT.c linux-libre-3.8.13-gnu1/net/ipv6/netfilter/ip6t_NPT.c
--- linux-libre-3.8-gnu1/net/ipv6/netfilter/ip6t_NPT.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/netfilter/ip6t_NPT.c	2013-05-11 16:57:46.000000000 -0400
@@ -57,7 +57,7 @@ static bool ip6t_npt_map_pfx(const struc
 		if (pfx_len - i >= 32)
 			mask = 0;
 		else
-			mask = htonl(~((1 << (pfx_len - i)) - 1));
+			mask = htonl((1 << (i - pfx_len + 32)) - 1);
 
 		idx = i / 32;
 		addr->s6_addr32[idx] &= mask;
diff -druNp linux-libre-3.8-gnu1/net/ipv6/netfilter/ip6t_rpfilter.c linux-libre-3.8.13-gnu1/net/ipv6/netfilter/ip6t_rpfilter.c
--- linux-libre-3.8-gnu1/net/ipv6/netfilter/ip6t_rpfilter.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/netfilter/ip6t_rpfilter.c	2013-05-11 16:57:46.000000000 -0400
@@ -71,6 +71,12 @@ static bool rpfilter_lookup_reverse6(con
 	return ret;
 }
 
+static bool rpfilter_is_local(const struct sk_buff *skb)
+{
+	const struct rt6_info *rt = (const void *) skb_dst(skb);
+	return rt && (rt->rt6i_flags & RTF_LOCAL);
+}
+
 static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_rpfilter_info *info = par->matchinfo;
@@ -78,7 +84,7 @@ static bool rpfilter_mt(const struct sk_
 	struct ipv6hdr *iph;
 	bool invert = info->flags & XT_RPFILTER_INVERT;
 
-	if (par->in->flags & IFF_LOOPBACK)
+	if (rpfilter_is_local(skb))
 		return true ^ invert;
 
 	iph = ipv6_hdr(skb);
diff -druNp linux-libre-3.8-gnu1/net/ipv6/netfilter/nf_conntrack_reasm.c linux-libre-3.8.13-gnu1/net/ipv6/netfilter/nf_conntrack_reasm.c
--- linux-libre-3.8-gnu1/net/ipv6/netfilter/nf_conntrack_reasm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/netfilter/nf_conntrack_reasm.c	2013-05-11 16:57:46.000000000 -0400
@@ -14,6 +14,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) "IPv6-nf: " fmt
+
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -180,13 +182,11 @@ static inline struct frag_queue *fq_find
 
 	q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
 	local_bh_enable();
-	if (q == NULL)
-		goto oom;
-
+	if (IS_ERR_OR_NULL(q)) {
+		inet_frag_maybe_warn_overflow(q, pr_fmt());
+		return NULL;
+	}
 	return container_of(q, struct frag_queue, q);
-
-oom:
-	return NULL;
 }
 
 
diff -druNp linux-libre-3.8-gnu1/net/ipv6/reassembly.c linux-libre-3.8.13-gnu1/net/ipv6/reassembly.c
--- linux-libre-3.8-gnu1/net/ipv6/reassembly.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/reassembly.c	2013-05-11 16:57:46.000000000 -0400
@@ -26,6 +26,9 @@
  *	YOSHIFUJI,H. @USAGI	Always remove fragment header to
  *				calculate ICV correctly.
  */
+
+#define pr_fmt(fmt) "IPv6: " fmt
+
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -197,9 +200,10 @@ fq_find(struct net *net, __be32 id, cons
 	hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);
 
 	q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
-	if (q == NULL)
+	if (IS_ERR_OR_NULL(q)) {
+		inet_frag_maybe_warn_overflow(q, pr_fmt());
 		return NULL;
-
+	}
 	return container_of(q, struct frag_queue, q);
 }
 
@@ -338,8 +342,17 @@ found:
 	}
 
 	if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
-	    fq->q.meat == fq->q.len)
-		return ip6_frag_reasm(fq, prev, dev);
+	    fq->q.meat == fq->q.len) {
+		int res;
+		unsigned long orefdst = skb->_skb_refdst;
+
+		skb->_skb_refdst = 0UL;
+		res = ip6_frag_reasm(fq, prev, dev);
+		skb->_skb_refdst = orefdst;
+		return res;
+	}
+
+	skb_dst_drop(skb);
 
 	write_lock(&ip6_frags.lock);
 	list_move_tail(&fq->q.lru_list, &fq->q.net->lru_list);
diff -druNp linux-libre-3.8-gnu1/net/ipv6/route.c linux-libre-3.8.13-gnu1/net/ipv6/route.c
--- linux-libre-3.8-gnu1/net/ipv6/route.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/route.c	2013-05-11 16:57:46.000000000 -0400
@@ -300,6 +300,7 @@ static void ip6_dst_destroy(struct dst_e
 {
 	struct rt6_info *rt = (struct rt6_info *)dst;
 	struct inet6_dev *idev = rt->rt6i_idev;
+	struct dst_entry *from = dst->from;
 
 	if (rt->n)
 		neigh_release(rt->n);
@@ -312,8 +313,8 @@ static void ip6_dst_destroy(struct dst_e
 		in6_dev_put(idev);
 	}
 
-	if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from)
-		dst_release(dst->from);
+	dst->from = NULL;
+	dst_release(from);
 
 	if (rt6_has_peer(rt)) {
 		struct inet_peer *peer = rt6_peer_ptr(rt);
@@ -1054,7 +1055,6 @@ struct dst_entry *ip6_blackhole_route(st
 
 		rt->rt6i_gateway = ort->rt6i_gateway;
 		rt->rt6i_flags = ort->rt6i_flags;
-		rt6_clean_expires(rt);
 		rt->rt6i_metric = 0;
 
 		memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -1859,8 +1859,6 @@ static struct rt6_info *ip6_rt_copy(stru
 		if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
 		    (RTF_DEFAULT | RTF_ADDRCONF))
 			rt6_set_from(rt, ort);
-		else
-			rt6_clean_expires(rt);
 		rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -1992,7 +1990,8 @@ void rt6_purge_dflt_routers(struct net *
 restart:
 	read_lock_bh(&table->tb6_lock);
 	for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
-		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
+		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
+		    (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
 			dst_hold(&rt->dst);
 			read_unlock_bh(&table->tb6_lock);
 			ip6_del_rt(rt);
diff -druNp linux-libre-3.8-gnu1/net/ipv6/tcp_ipv6.c linux-libre-3.8.13-gnu1/net/ipv6/tcp_ipv6.c
--- linux-libre-3.8-gnu1/net/ipv6/tcp_ipv6.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/tcp_ipv6.c	2013-05-11 16:57:46.000000000 -0400
@@ -386,9 +386,17 @@ static void tcp_v6_err(struct sk_buff *s
 
 		if (dst)
 			dst->ops->redirect(dst, sk, skb);
+		goto out;
 	}
 
 	if (type == ICMPV6_PKT_TOOBIG) {
+		/* We are not interested in TCP_LISTEN and open_requests
+		 * (SYN-ACKs send out by Linux are always <576bytes so
+		 * they should go through unfragmented).
+		 */
+		if (sk->sk_state == TCP_LISTEN)
+			goto out;
+
 		tp->mtu_info = ntohl(info);
 		if (!sock_owned_by_user(sk))
 			tcp_v6_mtu_reduced(sk);
diff -druNp linux-libre-3.8-gnu1/net/ipv6/xfrm6_policy.c linux-libre-3.8.13-gnu1/net/ipv6/xfrm6_policy.c
--- linux-libre-3.8-gnu1/net/ipv6/xfrm6_policy.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/ipv6/xfrm6_policy.c	2013-05-11 16:57:46.000000000 -0400
@@ -236,6 +236,8 @@ static void xfrm6_dst_destroy(struct dst
 {
 	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
 
+	if (likely(xdst->u.rt6.n))
+		neigh_release(xdst->u.rt6.n);
 	if (likely(xdst->u.rt6.rt6i_idev))
 		in6_dev_put(xdst->u.rt6.rt6i_idev);
 	dst_destroy_metrics_generic(dst);
diff -druNp linux-libre-3.8-gnu1/net/irda/af_irda.c linux-libre-3.8.13-gnu1/net/irda/af_irda.c
--- linux-libre-3.8-gnu1/net/irda/af_irda.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/irda/af_irda.c	2013-05-11 16:57:46.000000000 -0400
@@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kio
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
+	msg->msg_namelen = 0;
+
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 				flags & MSG_DONTWAIT, &err);
 	if (!skb)
@@ -2584,8 +2586,10 @@ bed:
 				    NULL, NULL, NULL);
 
 		/* Check if the we got some results */
-		if (!self->cachedaddr)
-			return -EAGAIN;		/* Didn't find any devices */
+		if (!self->cachedaddr) {
+			err = -EAGAIN;		/* Didn't find any devices */
+			goto out;
+		}
 		daddr = self->cachedaddr;
 		/* Cleanup */
 		self->cachedaddr = 0;
diff -druNp linux-libre-3.8-gnu1/net/iucv/af_iucv.c linux-libre-3.8.13-gnu1/net/iucv/af_iucv.c
--- linux-libre-3.8-gnu1/net/iucv/af_iucv.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/iucv/af_iucv.c	2013-05-11 16:57:46.000000000 -0400
@@ -1331,6 +1331,8 @@ static int iucv_sock_recvmsg(struct kioc
 	struct sk_buff *skb, *rskb, *cskb;
 	int err = 0;
 
+	msg->msg_namelen = 0;
+
 	if ((sk->sk_state == IUCV_DISCONN) &&
 	    skb_queue_empty(&iucv->backlog_skb_q) &&
 	    skb_queue_empty(&sk->sk_receive_queue) &&
diff -druNp linux-libre-3.8-gnu1/net/l2tp/l2tp_ip6.c linux-libre-3.8.13-gnu1/net/l2tp/l2tp_ip6.c
--- linux-libre-3.8-gnu1/net/l2tp/l2tp_ip6.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/l2tp/l2tp_ip6.c	2013-05-11 16:57:46.000000000 -0400
@@ -684,6 +684,7 @@ static int l2tp_ip6_recvmsg(struct kiocb
 		lsa->l2tp_addr = ipv6_hdr(skb)->saddr;
 		lsa->l2tp_flowinfo = 0;
 		lsa->l2tp_scope_id = 0;
+		lsa->l2tp_conn_id = 0;
 		if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
 			lsa->l2tp_scope_id = IP6CB(skb)->iif;
 	}
diff -druNp linux-libre-3.8-gnu1/net/l2tp/l2tp_ppp.c linux-libre-3.8.13-gnu1/net/l2tp/l2tp_ppp.c
--- linux-libre-3.8-gnu1/net/l2tp/l2tp_ppp.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/l2tp/l2tp_ppp.c	2013-05-11 16:57:46.000000000 -0400
@@ -355,6 +355,7 @@ static int pppol2tp_sendmsg(struct kiocb
 	l2tp_xmit_skb(session, skb, session->hdr_len);
 
 	sock_put(ps->tunnel_sock);
+	sock_put(sk);
 
 	return error;
 
diff -druNp linux-libre-3.8-gnu1/net/llc/af_llc.c linux-libre-3.8.13-gnu1/net/llc/af_llc.c
--- linux-libre-3.8-gnu1/net/llc/af_llc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/llc/af_llc.c	2013-05-11 16:57:46.000000000 -0400
@@ -720,6 +720,8 @@ static int llc_ui_recvmsg(struct kiocb *
 	int target;	/* Read at least this many bytes */
 	long timeo;
 
+	msg->msg_namelen = 0;
+
 	lock_sock(sk);
 	copied = -ENOTCONN;
 	if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
diff -druNp linux-libre-3.8-gnu1/net/mac80211/cfg.c linux-libre-3.8.13-gnu1/net/mac80211/cfg.c
--- linux-libre-3.8-gnu1/net/mac80211/cfg.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/mac80211/cfg.c	2013-05-11 16:57:46.000000000 -0400
@@ -2499,7 +2499,7 @@ static int ieee80211_cancel_roc(struct i
 			list_del(&dep->list);
 			mutex_unlock(&local->mtx);
 
-			ieee80211_roc_notify_destroy(dep);
+			ieee80211_roc_notify_destroy(dep, true);
 			return 0;
 		}
 
@@ -2539,7 +2539,7 @@ static int ieee80211_cancel_roc(struct i
 			ieee80211_start_next_roc(local);
 		mutex_unlock(&local->mtx);
 
-		ieee80211_roc_notify_destroy(found);
+		ieee80211_roc_notify_destroy(found, true);
 	} else {
 		/* work may be pending so use it all the time */
 		found->abort = true;
@@ -2549,6 +2549,8 @@ static int ieee80211_cancel_roc(struct i
 
 		/* work will clean up etc */
 		flush_delayed_work(&found->work);
+		WARN_ON(!found->to_be_freed);
+		kfree(found);
 	}
 
 	return 0;
diff -druNp linux-libre-3.8-gnu1/net/mac80211/ieee80211_i.h linux-libre-3.8.13-gnu1/net/mac80211/ieee80211_i.h
--- linux-libre-3.8-gnu1/net/mac80211/ieee80211_i.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/mac80211/ieee80211_i.h	2013-05-11 16:57:46.000000000 -0400
@@ -346,6 +346,7 @@ struct ieee80211_roc_work {
 	struct ieee80211_channel *chan;
 
 	bool started, abort, hw_begun, notified;
+	bool to_be_freed;
 
 	unsigned long hw_start_time;
 
@@ -1363,7 +1364,7 @@ void ieee80211_offchannel_return(struct
 void ieee80211_roc_setup(struct ieee80211_local *local);
 void ieee80211_start_next_roc(struct ieee80211_local *local);
 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc);
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
 void ieee80211_sw_roc_work(struct work_struct *work);
 void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
diff -druNp linux-libre-3.8-gnu1/net/mac80211/mlme.c linux-libre-3.8.13-gnu1/net/mac80211/mlme.c
--- linux-libre-3.8-gnu1/net/mac80211/mlme.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/mac80211/mlme.c	2013-05-11 16:57:46.000000000 -0400
@@ -1812,6 +1812,8 @@ static void __ieee80211_disconnect(struc
 			       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
 			       transmit_frame, frame_buf);
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
+	ieee80211_wake_queues_by_reason(&sdata->local->hw,
+					IEEE80211_QUEUE_STOP_REASON_CSA);
 	mutex_unlock(&ifmgd->mtx);
 
 	/*
@@ -1856,8 +1858,6 @@ static void ieee80211_csa_connection_dro
 		container_of(work, struct ieee80211_sub_if_data,
 			     u.mgd.csa_connection_drop_work);
 
-	ieee80211_wake_queues_by_reason(&sdata->local->hw,
-					IEEE80211_QUEUE_STOP_REASON_CSA);
 	__ieee80211_disconnect(sdata, true);
 }
 
@@ -3401,6 +3401,10 @@ ieee80211_determine_chantype(struct ieee
 	ret = 0;
 
 out:
+	/* don't print the message below for VHT mismatch if VHT is disabled */
+	if (ret & IEEE80211_STA_DISABLE_VHT)
+		vht_chandef = *chandef;
+
 	while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
 					IEEE80211_CHAN_DISABLED)) {
 		if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
@@ -3719,8 +3723,16 @@ int ieee80211_mgd_auth(struct ieee80211_
 	/* prep auth_data so we don't go into idle on disassoc */
 	ifmgd->auth_data = auth_data;
 
-	if (ifmgd->associated)
-		ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+	if (ifmgd->associated) {
+		u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+				       WLAN_REASON_UNSPECIFIED,
+				       false, frame_buf);
+
+		__cfg80211_send_deauth(sdata->dev, frame_buf,
+				       sizeof(frame_buf));
+	}
 
 	sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
 
@@ -3779,8 +3791,16 @@ int ieee80211_mgd_assoc(struct ieee80211
 
 	mutex_lock(&ifmgd->mtx);
 
-	if (ifmgd->associated)
-		ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+	if (ifmgd->associated) {
+		u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+				       WLAN_REASON_UNSPECIFIED,
+				       false, frame_buf);
+
+		__cfg80211_send_deauth(sdata->dev, frame_buf,
+				       sizeof(frame_buf));
+	}
 
 	if (ifmgd->auth_data && !ifmgd->auth_data->done) {
 		err = -EBUSY;
@@ -4072,6 +4092,17 @@ void ieee80211_mgd_stop(struct ieee80211
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+	/*
+	 * Make sure some work items will not run after this,
+	 * they will not do anything but might not have been
+	 * cancelled when disconnecting.
+	 */
+	cancel_work_sync(&ifmgd->monitor_work);
+	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+	cancel_work_sync(&ifmgd->request_smps_work);
+	cancel_work_sync(&ifmgd->csa_connection_drop_work);
+	cancel_work_sync(&ifmgd->chswitch_work);
+
 	mutex_lock(&ifmgd->mtx);
 	if (ifmgd->assoc_data)
 		ieee80211_destroy_assoc_data(sdata, false);
diff -druNp linux-libre-3.8-gnu1/net/mac80211/offchannel.c linux-libre-3.8.13-gnu1/net/mac80211/offchannel.c
--- linux-libre-3.8-gnu1/net/mac80211/offchannel.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/mac80211/offchannel.c	2013-05-11 16:57:46.000000000 -0400
@@ -299,10 +299,13 @@ void ieee80211_start_next_roc(struct iee
 	}
 }
 
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free)
 {
 	struct ieee80211_roc_work *dep, *tmp;
 
+	if (WARN_ON(roc->to_be_freed))
+		return;
+
 	/* was never transmitted */
 	if (roc->frame) {
 		cfg80211_mgmt_tx_status(&roc->sdata->wdev,
@@ -318,9 +321,12 @@ void ieee80211_roc_notify_destroy(struct
 						   GFP_KERNEL);
 
 	list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
-		ieee80211_roc_notify_destroy(dep);
+		ieee80211_roc_notify_destroy(dep, true);
 
-	kfree(roc);
+	if (free)
+		kfree(roc);
+	else
+		roc->to_be_freed = true;
 }
 
 void ieee80211_sw_roc_work(struct work_struct *work)
@@ -333,6 +339,9 @@ void ieee80211_sw_roc_work(struct work_s
 
 	mutex_lock(&local->mtx);
 
+	if (roc->to_be_freed)
+		goto out_unlock;
+
 	if (roc->abort)
 		goto finish;
 
@@ -372,7 +381,7 @@ void ieee80211_sw_roc_work(struct work_s
  finish:
 		list_del(&roc->list);
 		started = roc->started;
-		ieee80211_roc_notify_destroy(roc);
+		ieee80211_roc_notify_destroy(roc, !roc->abort);
 
 		if (started) {
 			drv_flush(local, false);
@@ -412,7 +421,7 @@ static void ieee80211_hw_roc_done(struct
 
 	list_del(&roc->list);
 
-	ieee80211_roc_notify_destroy(roc);
+	ieee80211_roc_notify_destroy(roc, true);
 
 	/* if there's another roc, start it now */
 	ieee80211_start_next_roc(local);
@@ -462,12 +471,14 @@ void ieee80211_roc_purge(struct ieee8021
 	list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
 		if (local->ops->remain_on_channel) {
 			list_del(&roc->list);
-			ieee80211_roc_notify_destroy(roc);
+			ieee80211_roc_notify_destroy(roc, true);
 		} else {
 			ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
 
 			/* work will clean up etc */
 			flush_delayed_work(&roc->work);
+			WARN_ON(!roc->to_be_freed);
+			kfree(roc);
 		}
 	}
 
diff -druNp linux-libre-3.8-gnu1/net/mac80211/pm.c linux-libre-3.8.13-gnu1/net/mac80211/pm.c
--- linux-libre-3.8-gnu1/net/mac80211/pm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/mac80211/pm.c	2013-05-11 16:57:46.000000000 -0400
@@ -52,8 +52,8 @@ int __ieee80211_suspend(struct ieee80211
 	ieee80211_stop_queues_by_reason(hw,
 			IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
-	/* flush out all packets */
-	synchronize_net();
+	/* flush out all packets and station cleanup call_rcu()s */
+	rcu_barrier();
 
 	drv_flush(local, false);
 
diff -druNp linux-libre-3.8-gnu1/net/mac80211/sta_info.c linux-libre-3.8.13-gnu1/net/mac80211/sta_info.c
--- linux-libre-3.8-gnu1/net/mac80211/sta_info.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/mac80211/sta_info.c	2013-05-11 16:57:46.000000000 -0400
@@ -756,6 +756,7 @@ int __must_check __sta_info_destroy(stru
 	struct ieee80211_local *local;
 	struct ieee80211_sub_if_data *sdata;
 	int ret, i;
+	bool have_key = false;
 
 	might_sleep();
 
@@ -783,12 +784,19 @@ int __must_check __sta_info_destroy(stru
 	list_del_rcu(&sta->list);
 
 	mutex_lock(&local->key_mtx);
-	for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 		__ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
-	if (sta->ptk)
+		have_key = true;
+	}
+	if (sta->ptk) {
 		__ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
+		have_key = true;
+	}
 	mutex_unlock(&local->key_mtx);
 
+	if (!have_key)
+		synchronize_net();
+
 	sta->dead = true;
 
 	local->num_sta--;
diff -druNp linux-libre-3.8-gnu1/net/netfilter/ipset/ip_set_core.c linux-libre-3.8.13-gnu1/net/netfilter/ipset/ip_set_core.c
--- linux-libre-3.8-gnu1/net/netfilter/ipset/ip_set_core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/ipset/ip_set_core.c	2013-05-11 16:57:46.000000000 -0400
@@ -1470,7 +1470,8 @@ ip_set_utest(struct sock *ctnl, struct s
 	if (ret == -EAGAIN)
 		ret = 1;
 
-	return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST;
+	return (ret < 0 && ret != -ENOTEMPTY) ? ret :
+		ret > 0 ? 0 : -IPSET_ERR_EXIST;
 }
 
 /* Get headed data of a set */
diff -druNp linux-libre-3.8-gnu1/net/netfilter/ipset/ip_set_list_set.c linux-libre-3.8.13-gnu1/net/netfilter/ipset/ip_set_list_set.c
--- linux-libre-3.8-gnu1/net/netfilter/ipset/ip_set_list_set.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/ipset/ip_set_list_set.c	2013-05-11 16:57:46.000000000 -0400
@@ -174,9 +174,13 @@ list_set_add(struct list_set *map, u32 i
 {
 	const struct set_elem *e = list_set_elem(map, i);
 
-	if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
-		/* Last element replaced: e.g. add new,before,last */
-		ip_set_put_byindex(e->id);
+	if (e->id != IPSET_INVALID_ID) {
+		const struct set_elem *x = list_set_elem(map, map->size - 1);
+
+		/* Last element replaced or pushed off */
+		if (x->id != IPSET_INVALID_ID)
+			ip_set_put_byindex(x->id);
+	}
 	if (with_timeout(map->timeout))
 		list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
 	else
diff -druNp linux-libre-3.8-gnu1/net/netfilter/ipvs/ip_vs_pe_sip.c linux-libre-3.8.13-gnu1/net/netfilter/ipvs/ip_vs_pe_sip.c
--- linux-libre-3.8-gnu1/net/netfilter/ipvs/ip_vs_pe_sip.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/ipvs/ip_vs_pe_sip.c	2013-05-11 16:57:46.000000000 -0400
@@ -37,14 +37,10 @@ static int get_callid(const char *dptr,
 		if (ret > 0)
 			break;
 		if (!ret)
-			return 0;
+			return -EINVAL;
 		dataoff += *matchoff;
 	}
 
-	/* Empty callid is useless */
-	if (!*matchlen)
-		return -EINVAL;
-
 	/* Too large is useless */
 	if (*matchlen > IP_VS_PEDATA_MAXLEN)
 		return -EINVAL;
diff -druNp linux-libre-3.8-gnu1/net/netfilter/nf_conntrack_helper.c linux-libre-3.8.13-gnu1/net/netfilter/nf_conntrack_helper.c
--- linux-libre-3.8-gnu1/net/netfilter/nf_conntrack_helper.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/nf_conntrack_helper.c	2013-05-11 16:57:46.000000000 -0400
@@ -236,7 +236,9 @@ int __nf_ct_try_assign_helper(struct nf_
 		/* We only allow helper re-assignment of the same sort since
 		 * we cannot reallocate the helper extension area.
 		 */
-		if (help->helper != helper) {
+		struct nf_conntrack_helper *tmp = rcu_dereference(help->helper);
+
+		if (tmp && tmp->help != helper->help) {
 			RCU_INIT_POINTER(help->helper, NULL);
 			goto out;
 		}
diff -druNp linux-libre-3.8-gnu1/net/netfilter/nf_conntrack_netlink.c linux-libre-3.8.13-gnu1/net/netfilter/nf_conntrack_netlink.c
--- linux-libre-3.8-gnu1/net/netfilter/nf_conntrack_netlink.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/nf_conntrack_netlink.c	2013-05-11 16:57:46.000000000 -0400
@@ -1705,6 +1705,9 @@ ctnetlink_new_conntrack(struct sock *ctn
 		if (nlh->nlmsg_flags & NLM_F_CREATE) {
 			enum ip_conntrack_events events;
 
+			if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY])
+				return -EINVAL;
+
 			ct = ctnetlink_create_conntrack(net, zone, cda, &otuple,
 							&rtuple, u3);
 			if (IS_ERR(ct))
diff -druNp linux-libre-3.8-gnu1/net/netfilter/nf_conntrack_sip.c linux-libre-3.8.13-gnu1/net/netfilter/nf_conntrack_sip.c
--- linux-libre-3.8-gnu1/net/netfilter/nf_conntrack_sip.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/nf_conntrack_sip.c	2013-05-11 16:57:46.000000000 -0400
@@ -1547,7 +1547,7 @@ static int sip_help_tcp(struct sk_buff *
 
 		msglen = origlen = end - dptr;
 		if (msglen > datalen)
-			return NF_DROP;
+			return NF_ACCEPT;
 
 		ret = process_sip_msg(skb, ct, protoff, dataoff,
 				      &dptr, &msglen);
diff -druNp linux-libre-3.8-gnu1/net/netfilter/nf_nat_core.c linux-libre-3.8.13-gnu1/net/netfilter/nf_nat_core.c
--- linux-libre-3.8-gnu1/net/netfilter/nf_nat_core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netfilter/nf_nat_core.c	2013-05-11 16:57:46.000000000 -0400
@@ -468,33 +468,22 @@ EXPORT_SYMBOL_GPL(nf_nat_packet);
 struct nf_nat_proto_clean {
 	u8	l3proto;
 	u8	l4proto;
-	bool	hash;
 };
 
-/* Clear NAT section of all conntracks, in case we're loaded again. */
-static int nf_nat_proto_clean(struct nf_conn *i, void *data)
+/* kill conntracks with affected NAT section */
+static int nf_nat_proto_remove(struct nf_conn *i, void *data)
 {
 	const struct nf_nat_proto_clean *clean = data;
 	struct nf_conn_nat *nat = nfct_nat(i);
 
 	if (!nat)
 		return 0;
-	if (!(i->status & IPS_SRC_NAT_DONE))
-		return 0;
+
 	if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) ||
 	    (clean->l4proto && nf_ct_protonum(i) != clean->l4proto))
 		return 0;
 
-	if (clean->hash) {
-		spin_lock_bh(&nf_nat_lock);
-		hlist_del_rcu(&nat->bysource);
-		spin_unlock_bh(&nf_nat_lock);
-	} else {
-		memset(nat, 0, sizeof(*nat));
-		i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK |
-			       IPS_SEQ_ADJUST);
-	}
-	return 0;
+	return i->status & IPS_NAT_MASK ? 1 : 0;
 }
 
 static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
@@ -506,16 +495,8 @@ static void nf_nat_l4proto_clean(u8 l3pr
 	struct net *net;
 
 	rtnl_lock();
-	/* Step 1 - remove from bysource hash */
-	clean.hash = true;
-	for_each_net(net)
-		nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
-	synchronize_rcu();
-
-	/* Step 2 - clean NAT section */
-	clean.hash = false;
 	for_each_net(net)
-		nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
+		nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
 	rtnl_unlock();
 }
 
@@ -527,16 +508,9 @@ static void nf_nat_l3proto_clean(u8 l3pr
 	struct net *net;
 
 	rtnl_lock();
-	/* Step 1 - remove from bysource hash */
-	clean.hash = true;
-	for_each_net(net)
-		nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
-	synchronize_rcu();
 
-	/* Step 2 - clean NAT section */
-	clean.hash = false;
 	for_each_net(net)
-		nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
+		nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
 	rtnl_unlock();
 }
 
@@ -774,7 +748,7 @@ static void __net_exit nf_nat_net_exit(s
 {
 	struct nf_nat_proto_clean clean = {};
 
-	nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean);
+	nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
 	synchronize_rcu();
 	nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
 }
diff -druNp linux-libre-3.8-gnu1/net/netlabel/netlabel_unlabeled.c linux-libre-3.8.13-gnu1/net/netlabel/netlabel_unlabeled.c
--- linux-libre-3.8-gnu1/net/netlabel/netlabel_unlabeled.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netlabel/netlabel_unlabeled.c	2013-05-11 16:57:46.000000000 -0400
@@ -1189,8 +1189,6 @@ static int netlbl_unlabel_staticlist(str
 	struct netlbl_unlhsh_walk_arg cb_arg;
 	u32 skip_bkt = cb->args[0];
 	u32 skip_chain = cb->args[1];
-	u32 skip_addr4 = cb->args[2];
-	u32 skip_addr6 = cb->args[3];
 	u32 iter_bkt;
 	u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
 	struct netlbl_unlhsh_iface *iface;
@@ -1215,7 +1213,7 @@ static int netlbl_unlabel_staticlist(str
 				continue;
 			netlbl_af4list_foreach_rcu(addr4,
 						   &iface->addr4_list) {
-				if (iter_addr4++ < skip_addr4)
+				if (iter_addr4++ < cb->args[2])
 					continue;
 				if (netlbl_unlabel_staticlist_gen(
 					      NLBL_UNLABEL_C_STATICLIST,
@@ -1231,7 +1229,7 @@ static int netlbl_unlabel_staticlist(str
 #if IS_ENABLED(CONFIG_IPV6)
 			netlbl_af6list_foreach_rcu(addr6,
 						   &iface->addr6_list) {
-				if (iter_addr6++ < skip_addr6)
+				if (iter_addr6++ < cb->args[3])
 					continue;
 				if (netlbl_unlabel_staticlist_gen(
 					      NLBL_UNLABEL_C_STATICLIST,
@@ -1250,10 +1248,10 @@ static int netlbl_unlabel_staticlist(str
 
 unlabel_staticlist_return:
 	rcu_read_unlock();
-	cb->args[0] = skip_bkt;
-	cb->args[1] = skip_chain;
-	cb->args[2] = skip_addr4;
-	cb->args[3] = skip_addr6;
+	cb->args[0] = iter_bkt;
+	cb->args[1] = iter_chain;
+	cb->args[2] = iter_addr4;
+	cb->args[3] = iter_addr6;
 	return skb->len;
 }
 
@@ -1273,12 +1271,9 @@ static int netlbl_unlabel_staticlistdef(
 {
 	struct netlbl_unlhsh_walk_arg cb_arg;
 	struct netlbl_unlhsh_iface *iface;
-	u32 skip_addr4 = cb->args[0];
-	u32 skip_addr6 = cb->args[1];
-	u32 iter_addr4 = 0;
+	u32 iter_addr4 = 0, iter_addr6 = 0;
 	struct netlbl_af4list *addr4;
 #if IS_ENABLED(CONFIG_IPV6)
-	u32 iter_addr6 = 0;
 	struct netlbl_af6list *addr6;
 #endif
 
@@ -1292,7 +1287,7 @@ static int netlbl_unlabel_staticlistdef(
 		goto unlabel_staticlistdef_return;
 
 	netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
-		if (iter_addr4++ < skip_addr4)
+		if (iter_addr4++ < cb->args[0])
 			continue;
 		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
 					      iface,
@@ -1305,7 +1300,7 @@ static int netlbl_unlabel_staticlistdef(
 	}
 #if IS_ENABLED(CONFIG_IPV6)
 	netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
-		if (iter_addr6++ < skip_addr6)
+		if (iter_addr6++ < cb->args[1])
 			continue;
 		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
 					      iface,
@@ -1320,8 +1315,8 @@ static int netlbl_unlabel_staticlistdef(
 
 unlabel_staticlistdef_return:
 	rcu_read_unlock();
-	cb->args[0] = skip_addr4;
-	cb->args[1] = skip_addr6;
+	cb->args[0] = iter_addr4;
+	cb->args[1] = iter_addr6;
 	return skb->len;
 }
 
diff -druNp linux-libre-3.8-gnu1/net/netlink/genetlink.c linux-libre-3.8.13-gnu1/net/netlink/genetlink.c
--- linux-libre-3.8-gnu1/net/netlink/genetlink.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netlink/genetlink.c	2013-05-11 16:57:46.000000000 -0400
@@ -142,6 +142,7 @@ int genl_register_mc_group(struct genl_f
 	int err = 0;
 
 	BUG_ON(grp->name[0] == '\0');
+	BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL);
 
 	genl_lock();
 
diff -druNp linux-libre-3.8-gnu1/net/netrom/af_netrom.c linux-libre-3.8.13-gnu1/net/netrom/af_netrom.c
--- linux-libre-3.8-gnu1/net/netrom/af_netrom.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/netrom/af_netrom.c	2013-05-11 16:57:46.000000000 -0400
@@ -1177,6 +1177,7 @@ static int nr_recvmsg(struct kiocb *iocb
 	}
 
 	if (sax != NULL) {
+		memset(sax, 0, sizeof(sax));
 		sax->sax25_family = AF_NETROM;
 		skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
 			      AX25_ADDR_LEN);
diff -druNp linux-libre-3.8-gnu1/net/nfc/llcp/sock.c linux-libre-3.8.13-gnu1/net/nfc/llcp/sock.c
--- linux-libre-3.8-gnu1/net/nfc/llcp/sock.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/nfc/llcp/sock.c	2013-05-11 16:57:46.000000000 -0400
@@ -644,6 +644,8 @@ static int llcp_sock_recvmsg(struct kioc
 
 	pr_debug("%p %zu\n", sk, len);
 
+	msg->msg_namelen = 0;
+
 	lock_sock(sk);
 
 	if (sk->sk_state == LLCP_CLOSED &&
@@ -684,6 +686,7 @@ static int llcp_sock_recvmsg(struct kioc
 
 		pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap);
 
+		memset(&sockaddr, 0, sizeof(sockaddr));
 		sockaddr.sa_family = AF_NFC;
 		sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP;
 		sockaddr.dsap = ui_cb->dsap;
diff -druNp linux-libre-3.8-gnu1/net/rds/message.c linux-libre-3.8.13-gnu1/net/rds/message.c
--- linux-libre-3.8-gnu1/net/rds/message.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/rds/message.c	2013-05-11 16:57:46.000000000 -0400
@@ -197,6 +197,9 @@ struct rds_message *rds_message_alloc(un
 {
 	struct rds_message *rm;
 
+	if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message))
+		return NULL;
+
 	rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp);
 	if (!rm)
 		goto out;
diff -druNp linux-libre-3.8-gnu1/net/rose/af_rose.c linux-libre-3.8.13-gnu1/net/rose/af_rose.c
--- linux-libre-3.8-gnu1/net/rose/af_rose.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/rose/af_rose.c	2013-05-11 16:57:46.000000000 -0400
@@ -1257,6 +1257,7 @@ static int rose_recvmsg(struct kiocb *io
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
 	if (srose != NULL) {
+		memset(srose, 0, msg->msg_namelen);
 		srose->srose_family = AF_ROSE;
 		srose->srose_addr   = rose->dest_addr;
 		srose->srose_call   = rose->dest_call;
diff -druNp linux-libre-3.8-gnu1/net/sched/sch_cbq.c linux-libre-3.8.13-gnu1/net/sched/sch_cbq.c
--- linux-libre-3.8-gnu1/net/sched/sch_cbq.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sched/sch_cbq.c	2013-05-11 16:57:46.000000000 -0400
@@ -962,8 +962,11 @@ cbq_dequeue(struct Qdisc *sch)
 		cbq_update(q);
 		if ((incr -= incr2) < 0)
 			incr = 0;
+		q->now += incr;
+	} else {
+		if (now > q->now)
+			q->now = now;
 	}
-	q->now += incr;
 	q->now_rt = now;
 
 	for (;;) {
diff -druNp linux-libre-3.8-gnu1/net/sched/sch_fq_codel.c linux-libre-3.8.13-gnu1/net/sched/sch_fq_codel.c
--- linux-libre-3.8-gnu1/net/sched/sch_fq_codel.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sched/sch_fq_codel.c	2013-05-11 16:57:46.000000000 -0400
@@ -195,7 +195,7 @@ static int fq_codel_enqueue(struct sk_bu
 		flow->deficit = q->quantum;
 		flow->dropped = 0;
 	}
-	if (++sch->q.qlen < sch->limit)
+	if (++sch->q.qlen <= sch->limit)
 		return NET_XMIT_SUCCESS;
 
 	q->drop_overlimit++;
diff -druNp linux-libre-3.8-gnu1/net/sctp/associola.c linux-libre-3.8.13-gnu1/net/sctp/associola.c
--- linux-libre-3.8-gnu1/net/sctp/associola.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sctp/associola.c	2013-05-11 16:57:46.000000000 -0400
@@ -1080,7 +1080,7 @@ struct sctp_transport *sctp_assoc_lookup
 			transports) {
 
 		if (transport == active)
-			break;
+			continue;
 		list_for_each_entry(chunk, &transport->transmitted,
 				transmitted_list) {
 			if (key == chunk->subh.data_hdr->tsn) {
diff -druNp linux-libre-3.8-gnu1/net/sctp/sm_statefuns.c linux-libre-3.8.13-gnu1/net/sctp/sm_statefuns.c
--- linux-libre-3.8-gnu1/net/sctp/sm_statefuns.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sctp/sm_statefuns.c	2013-05-11 16:57:46.000000000 -0400
@@ -2082,7 +2082,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupc
 	}
 
 	/* Delete the tempory new association. */
-	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
+	sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc));
 	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
 
 	/* Restore association pointer to provide SCTP command interpeter
diff -druNp linux-libre-3.8-gnu1/net/sctp/socket.c linux-libre-3.8.13-gnu1/net/sctp/socket.c
--- linux-libre-3.8-gnu1/net/sctp/socket.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sctp/socket.c	2013-05-11 16:57:46.000000000 -0400
@@ -5653,6 +5653,9 @@ static int sctp_getsockopt_assoc_stats(s
 	if (len < sizeof(sctp_assoc_t))
 		return -EINVAL;
 
+	/* Allow the struct to grow and fill in as much as possible */
+	len = min_t(size_t, len, sizeof(sas));
+
 	if (copy_from_user(&sas, optval, len))
 		return -EFAULT;
 
@@ -5686,9 +5689,6 @@ static int sctp_getsockopt_assoc_stats(s
 	/* Mark beginning of a new observation period */
 	asoc->stats.max_obs_rto = asoc->rto_min;
 
-	/* Allow the struct to grow and fill in as much as possible */
-	len = min_t(size_t, len, sizeof(sas));
-
 	if (put_user(len, optlen))
 		return -EFAULT;
 
diff -druNp linux-libre-3.8-gnu1/net/sunrpc/clnt.c linux-libre-3.8.13-gnu1/net/sunrpc/clnt.c
--- linux-libre-3.8-gnu1/net/sunrpc/clnt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sunrpc/clnt.c	2013-05-11 16:57:46.000000000 -0400
@@ -511,7 +511,7 @@ static struct rpc_clnt *__rpc_clone_clie
 	new = rpc_new_client(args, xprt);
 	if (IS_ERR(new)) {
 		err = PTR_ERR(new);
-		goto out_put;
+		goto out_err;
 	}
 
 	atomic_inc(&clnt->cl_count);
@@ -524,8 +524,6 @@ static struct rpc_clnt *__rpc_clone_clie
 	new->cl_chatty = clnt->cl_chatty;
 	return new;
 
-out_put:
-	xprt_put(xprt);
 out_err:
 	dprintk("RPC:       %s: returned error %d\n", __func__, err);
 	return ERR_PTR(err);
diff -druNp linux-libre-3.8-gnu1/net/sunrpc/sched.c linux-libre-3.8.13-gnu1/net/sunrpc/sched.c
--- linux-libre-3.8-gnu1/net/sunrpc/sched.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sunrpc/sched.c	2013-05-11 16:57:46.000000000 -0400
@@ -180,6 +180,8 @@ static void __rpc_add_wait_queue(struct
 		list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
 	task->tk_waitqueue = queue;
 	queue->qlen++;
+	/* barrier matches the read in rpc_wake_up_task_queue_locked() */
+	smp_wmb();
 	rpc_set_queued(task);
 
 	dprintk("RPC: %5u added to queue %p \"%s\"\n",
@@ -430,8 +432,11 @@ static void __rpc_do_wake_up_task(struct
  */
 static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
-	if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
-		__rpc_do_wake_up_task(queue, task);
+	if (RPC_IS_QUEUED(task)) {
+		smp_rmb();
+		if (task->tk_waitqueue == queue)
+			__rpc_do_wake_up_task(queue, task);
+	}
 }
 
 /*
diff -druNp linux-libre-3.8-gnu1/net/sunrpc/svc.c linux-libre-3.8.13-gnu1/net/sunrpc/svc.c
--- linux-libre-3.8-gnu1/net/sunrpc/svc.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sunrpc/svc.c	2013-05-11 16:57:46.000000000 -0400
@@ -515,15 +515,6 @@ EXPORT_SYMBOL_GPL(svc_create_pooled);
 
 void svc_shutdown_net(struct svc_serv *serv, struct net *net)
 {
-	/*
-	 * The set of xprts (contained in the sv_tempsocks and
-	 * sv_permsocks lists) is now constant, since it is modified
-	 * only by accepting new sockets (done by service threads in
-	 * svc_recv) or aging old ones (done by sv_temptimer), or
-	 * configuration changes (excluded by whatever locking the
-	 * caller is using--nfsd_mutex in the case of nfsd).  So it's
-	 * safe to traverse those lists and shut everything down:
-	 */
 	svc_close_net(serv, net);
 
 	if (serv->sv_shutdown)
diff -druNp linux-libre-3.8-gnu1/net/sunrpc/svc_xprt.c linux-libre-3.8.13-gnu1/net/sunrpc/svc_xprt.c
--- linux-libre-3.8-gnu1/net/sunrpc/svc_xprt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sunrpc/svc_xprt.c	2013-05-11 16:57:46.000000000 -0400
@@ -856,7 +856,6 @@ static void svc_age_temp_xprts(unsigned
 	struct svc_serv *serv = (struct svc_serv *)closure;
 	struct svc_xprt *xprt;
 	struct list_head *le, *next;
-	LIST_HEAD(to_be_aged);
 
 	dprintk("svc_age_temp_xprts\n");
 
@@ -877,25 +876,15 @@ static void svc_age_temp_xprts(unsigned
 		if (atomic_read(&xprt->xpt_ref.refcount) > 1 ||
 		    test_bit(XPT_BUSY, &xprt->xpt_flags))
 			continue;
-		svc_xprt_get(xprt);
-		list_move(le, &to_be_aged);
+		list_del_init(le);
 		set_bit(XPT_CLOSE, &xprt->xpt_flags);
 		set_bit(XPT_DETACHED, &xprt->xpt_flags);
-	}
-	spin_unlock_bh(&serv->sv_lock);
-
-	while (!list_empty(&to_be_aged)) {
-		le = to_be_aged.next;
-		/* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */
-		list_del_init(le);
-		xprt = list_entry(le, struct svc_xprt, xpt_list);
-
 		dprintk("queuing xprt %p for closing\n", xprt);
 
 		/* a thread will dequeue and close it soon */
 		svc_xprt_enqueue(xprt);
-		svc_xprt_put(xprt);
 	}
+	spin_unlock_bh(&serv->sv_lock);
 
 	mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
 }
@@ -959,21 +948,24 @@ void svc_close_xprt(struct svc_xprt *xpr
 }
 EXPORT_SYMBOL_GPL(svc_close_xprt);
 
-static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
+static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
 {
 	struct svc_xprt *xprt;
+	int ret = 0;
 
 	spin_lock(&serv->sv_lock);
 	list_for_each_entry(xprt, xprt_list, xpt_list) {
 		if (xprt->xpt_net != net)
 			continue;
+		ret++;
 		set_bit(XPT_CLOSE, &xprt->xpt_flags);
-		set_bit(XPT_BUSY, &xprt->xpt_flags);
+		svc_xprt_enqueue(xprt);
 	}
 	spin_unlock(&serv->sv_lock);
+	return ret;
 }
 
-static void svc_clear_pools(struct svc_serv *serv, struct net *net)
+static struct svc_xprt *svc_dequeue_net(struct svc_serv *serv, struct net *net)
 {
 	struct svc_pool *pool;
 	struct svc_xprt *xprt;
@@ -988,42 +980,46 @@ static void svc_clear_pools(struct svc_s
 			if (xprt->xpt_net != net)
 				continue;
 			list_del_init(&xprt->xpt_ready);
+			spin_unlock_bh(&pool->sp_lock);
+			return xprt;
 		}
 		spin_unlock_bh(&pool->sp_lock);
 	}
+	return NULL;
 }
 
-static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
+static void svc_clean_up_xprts(struct svc_serv *serv, struct net *net)
 {
 	struct svc_xprt *xprt;
-	struct svc_xprt *tmp;
-	LIST_HEAD(victims);
-
-	spin_lock(&serv->sv_lock);
-	list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) {
-		if (xprt->xpt_net != net)
-			continue;
-		list_move(&xprt->xpt_list, &victims);
-	}
-	spin_unlock(&serv->sv_lock);
 
-	list_for_each_entry_safe(xprt, tmp, &victims, xpt_list)
+	while ((xprt = svc_dequeue_net(serv, net))) {
+		set_bit(XPT_CLOSE, &xprt->xpt_flags);
 		svc_delete_xprt(xprt);
+	}
 }
 
+/*
+ * Server threads may still be running (especially in the case where the
+ * service is still running in other network namespaces).
+ *
+ * So we shut down sockets the same way we would on a running server, by
+ * setting XPT_CLOSE, enqueuing, and letting a thread pick it up to do
+ * the close.  In the case there are no such other threads,
+ * threads running, svc_clean_up_xprts() does a simple version of a
+ * server's main event loop, and in the case where there are other
+ * threads, we may need to wait a little while and then check again to
+ * see if they're done.
+ */
 void svc_close_net(struct svc_serv *serv, struct net *net)
 {
-	svc_close_list(serv, &serv->sv_tempsocks, net);
-	svc_close_list(serv, &serv->sv_permsocks, net);
+	int delay = 0;
 
-	svc_clear_pools(serv, net);
-	/*
-	 * At this point the sp_sockets lists will stay empty, since
-	 * svc_xprt_enqueue will not add new entries without taking the
-	 * sp_lock and checking XPT_BUSY.
-	 */
-	svc_clear_list(serv, &serv->sv_tempsocks, net);
-	svc_clear_list(serv, &serv->sv_permsocks, net);
+	while (svc_close_list(serv, &serv->sv_permsocks, net) +
+	       svc_close_list(serv, &serv->sv_tempsocks, net)) {
+
+		svc_clean_up_xprts(serv, net);
+		msleep(delay++);
+	}
 }
 
 /*
diff -druNp linux-libre-3.8-gnu1/net/sunrpc/xprt.c linux-libre-3.8.13-gnu1/net/sunrpc/xprt.c
--- linux-libre-3.8-gnu1/net/sunrpc/xprt.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/sunrpc/xprt.c	2013-05-11 16:57:46.000000000 -0400
@@ -485,13 +485,17 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_task
  * xprt_wait_for_buffer_space - wait for transport output buffer to clear
  * @task: task to be put to sleep
  * @action: function pointer to be executed after wait
+ *
+ * Note that we only set the timer for the case of RPC_IS_SOFT(), since
+ * we don't in general want to force a socket disconnection due to
+ * an incomplete RPC call transmission.
  */
 void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
 {
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 
-	task->tk_timeout = req->rq_timeout;
+	task->tk_timeout = RPC_IS_SOFT(task) ? req->rq_timeout : 0;
 	rpc_sleep_on(&xprt->pending, task, action);
 }
 EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
diff -druNp linux-libre-3.8-gnu1/net/tipc/socket.c linux-libre-3.8.13-gnu1/net/tipc/socket.c
--- linux-libre-3.8-gnu1/net/tipc/socket.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/tipc/socket.c	2013-05-11 16:57:46.000000000 -0400
@@ -806,6 +806,7 @@ static void set_orig_addr(struct msghdr
 	if (addr) {
 		addr->family = AF_TIPC;
 		addr->addrtype = TIPC_ADDR_ID;
+		memset(&addr->addr, 0, sizeof(addr->addr));
 		addr->addr.id.ref = msg_origport(msg);
 		addr->addr.id.node = msg_orignode(msg);
 		addr->addr.name.domain = 0;	/* could leave uninitialized */
@@ -920,6 +921,9 @@ static int recv_msg(struct kiocb *iocb,
 		goto exit;
 	}
 
+	/* will be updated in set_orig_addr() if needed */
+	m->msg_namelen = 0;
+
 	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
@@ -1029,6 +1033,9 @@ static int recv_stream(struct kiocb *ioc
 		goto exit;
 	}
 
+	/* will be updated in set_orig_addr() if needed */
+	m->msg_namelen = 0;
+
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
 	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 
diff -druNp linux-libre-3.8-gnu1/net/unix/af_unix.c linux-libre-3.8.13-gnu1/net/unix/af_unix.c
--- linux-libre-3.8-gnu1/net/unix/af_unix.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/unix/af_unix.c	2013-05-11 16:57:46.000000000 -0400
@@ -384,7 +384,7 @@ static void unix_sock_destructor(struct
 #endif
 }
 
-static int unix_release_sock(struct sock *sk, int embrion)
+static void unix_release_sock(struct sock *sk, int embrion)
 {
 	struct unix_sock *u = unix_sk(sk);
 	struct path path;
@@ -453,8 +453,6 @@ static int unix_release_sock(struct sock
 
 	if (unix_tot_inflight)
 		unix_gc();		/* Garbage collect fds */
-
-	return 0;
 }
 
 static void init_peercred(struct sock *sk)
@@ -701,9 +699,10 @@ static int unix_release(struct socket *s
 	if (!sk)
 		return 0;
 
+	unix_release_sock(sk, 0);
 	sock->sk = NULL;
 
-	return unix_release_sock(sk, 0);
+	return 0;
 }
 
 static int unix_autobind(struct socket *sock)
@@ -1996,7 +1995,7 @@ again:
 			if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
 			    (UNIXCB(skb).cred != siocb->scm->cred))
 				break;
-		} else {
+		} else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
 			/* Copy credentials */
 			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
 			check_creds = 1;
diff -druNp linux-libre-3.8-gnu1/net/wireless/reg.c linux-libre-3.8.13-gnu1/net/wireless/reg.c
--- linux-libre-3.8-gnu1/net/wireless/reg.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/net/wireless/reg.c	2013-05-11 16:57:46.000000000 -0400
@@ -883,7 +883,7 @@ static void handle_channel(struct wiphy
 			return;
 
 		REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq);
-		chan->flags = IEEE80211_CHAN_DISABLED;
+		chan->flags |= IEEE80211_CHAN_DISABLED;
 		return;
 	}
 
diff -druNp linux-libre-3.8-gnu1/scripts/kconfig/streamline_config.pl linux-libre-3.8.13-gnu1/scripts/kconfig/streamline_config.pl
--- linux-libre-3.8-gnu1/scripts/kconfig/streamline_config.pl	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/scripts/kconfig/streamline_config.pl	2013-05-11 16:57:46.000000000 -0400
@@ -156,7 +156,6 @@ sub read_kconfig {
 
     my $state = "NONE";
     my $config;
-    my @kconfigs;
 
     my $cont = 0;
     my $line;
@@ -190,7 +189,13 @@ sub read_kconfig {
 
 	# collect any Kconfig sources
 	if (/^source\s*"(.*)"/) {
-	    $kconfigs[$#kconfigs+1] = $1;
+	    my $kconfig = $1;
+	    # prevent reading twice.
+	    if (!defined($read_kconfigs{$kconfig})) {
+		$read_kconfigs{$kconfig} = 1;
+		read_kconfig($kconfig);
+	    }
+	    next;
 	}
 
 	# configs found
@@ -250,14 +255,6 @@ sub read_kconfig {
 	}
     }
     close($kinfile);
-
-    # read in any configs that were found.
-    foreach my $kconfig (@kconfigs) {
-	if (!defined($read_kconfigs{$kconfig})) {
-	    $read_kconfigs{$kconfig} = 1;
-	    read_kconfig($kconfig);
-	}
-    }
 }
 
 if ($kconfig) {
diff -druNp linux-libre-3.8-gnu1/scripts/Makefile.headersinst linux-libre-3.8.13-gnu1/scripts/Makefile.headersinst
--- linux-libre-3.8-gnu1/scripts/Makefile.headersinst	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/scripts/Makefile.headersinst	2013-05-11 16:57:46.000000000 -0400
@@ -8,7 +8,7 @@
 # ==========================================================================
 
 # called may set destination dir (when installing to asm/)
-_dst := $(or $(destination-y),$(dst),$(obj))
+_dst := $(if $(destination-y),$(destination-y),$(if $(dst),$(dst),$(obj)))
 
 # generated header directory
 gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
@@ -48,13 +48,14 @@ all-files     := $(header-y) $(genhdr-y)
 output-files  := $(addprefix $(installdir)/, $(all-files))
 
 input-files   := $(foreach hdr, $(header-y), \
-		   $(or \
+		   $(if $(wildcard $(srcdir)/$(hdr)), \
 			$(wildcard $(srcdir)/$(hdr)), \
-			$(wildcard $(oldsrcdir)/$(hdr)), \
-			$(error Missing UAPI file $(srcdir)/$(hdr)) \
+			$(if $(wildcard $(oldsrcdir)/$(hdr)), \
+				$(wildcard $(oldsrcdir)/$(hdr)), \
+				$(error Missing UAPI file $(srcdir)/$(hdr))) \
 		   )) \
 		 $(foreach hdr, $(genhdr-y), \
-		   $(or \
+		   $(if	$(wildcard $(gendir)/$(hdr)), \
 			$(wildcard $(gendir)/$(hdr)), \
 			$(error Missing generated UAPI file $(gendir)/$(hdr)) \
 		   ))
diff -druNp linux-libre-3.8-gnu1/security/keys/compat.c linux-libre-3.8.13-gnu1/security/keys/compat.c
--- linux-libre-3.8-gnu1/security/keys/compat.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/security/keys/compat.c	2013-05-11 16:57:46.000000000 -0400
@@ -40,12 +40,12 @@ static long compat_keyctl_instantiate_ke
 					   ARRAY_SIZE(iovstack),
 					   iovstack, &iov);
 	if (ret < 0)
-		return ret;
+		goto err;
 	if (ret == 0)
 		goto no_payload_free;
 
 	ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-
+err:
 	if (iov != iovstack)
 		kfree(iov);
 	return ret;
diff -druNp linux-libre-3.8-gnu1/security/keys/process_keys.c linux-libre-3.8.13-gnu1/security/keys/process_keys.c
--- linux-libre-3.8-gnu1/security/keys/process_keys.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/security/keys/process_keys.c	2013-05-11 16:57:46.000000000 -0400
@@ -57,7 +57,7 @@ int install_user_keyrings(void)
 
 	kenter("%p{%u}", user, uid);
 
-	if (user->uid_keyring) {
+	if (user->uid_keyring && user->session_keyring) {
 		kleave(" = 0 [exist]");
 		return 0;
 	}
@@ -367,6 +367,8 @@ key_ref_t search_my_process_keyrings(str
 
 		switch (PTR_ERR(key_ref)) {
 		case -EAGAIN: /* no key */
+			if (ret)
+				break;
 		case -ENOKEY: /* negative key */
 			ret = key_ref;
 			break;
@@ -837,7 +839,7 @@ void key_change_session_keyring(struct c
 	new-> sgid	= old-> sgid;
 	new->fsgid	= old->fsgid;
 	new->user	= get_uid(old->user);
-	new->user_ns	= get_user_ns(new->user_ns);
+	new->user_ns	= get_user_ns(old->user_ns);
 	new->group_info	= get_group_info(old->group_info);
 
 	new->securebits	= old->securebits;
diff -druNp linux-libre-3.8-gnu1/security/selinux/xfrm.c linux-libre-3.8.13-gnu1/security/selinux/xfrm.c
--- linux-libre-3.8-gnu1/security/selinux/xfrm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/security/selinux/xfrm.c	2013-05-11 16:57:46.000000000 -0400
@@ -310,7 +310,7 @@ int selinux_xfrm_policy_clone(struct xfr
 
 	if (old_ctx) {
 		new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
-				  GFP_KERNEL);
+				  GFP_ATOMIC);
 		if (!new_ctx)
 			return -ENOMEM;
 
diff -druNp linux-libre-3.8-gnu1/sound/core/pcm_native.c linux-libre-3.8.13-gnu1/sound/core/pcm_native.c
--- linux-libre-3.8-gnu1/sound/core/pcm_native.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/core/pcm_native.c	2013-05-11 16:57:46.000000000 -0400
@@ -3222,18 +3222,10 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mm
 int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
 			   struct vm_area_struct *area)
 {
-	long size;
-	unsigned long offset;
+	struct snd_pcm_runtime *runtime = substream->runtime;;
 
 	area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
-	area->vm_flags |= VM_IO;
-	size = area->vm_end - area->vm_start;
-	offset = area->vm_pgoff << PAGE_SHIFT;
-	if (io_remap_pfn_range(area, area->vm_start,
-				(substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
-				size, area->vm_page_prot))
-		return -EAGAIN;
-	return 0;
+	return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
 }
 
 EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
diff -druNp linux-libre-3.8-gnu1/sound/core/seq/seq_timer.c linux-libre-3.8.13-gnu1/sound/core/seq/seq_timer.c
--- linux-libre-3.8-gnu1/sound/core/seq/seq_timer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/core/seq/seq_timer.c	2013-05-11 16:57:46.000000000 -0400
@@ -290,10 +290,10 @@ int snd_seq_timer_open(struct snd_seq_qu
 			tid.device = SNDRV_TIMER_GLOBAL_SYSTEM;
 			err = snd_timer_open(&t, str, &tid, q->queue);
 		}
-		if (err < 0) {
-			snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
-			return err;
-		}
+	}
+	if (err < 0) {
+		snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
+		return err;
 	}
 	t->callback = snd_seq_timer_interrupt;
 	t->callback_data = q;
diff -druNp linux-libre-3.8-gnu1/sound/core/vmaster.c linux-libre-3.8.13-gnu1/sound/core/vmaster.c
--- linux-libre-3.8-gnu1/sound/core/vmaster.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/core/vmaster.c	2013-05-11 16:57:46.000000000 -0400
@@ -213,7 +213,10 @@ static int slave_put(struct snd_kcontrol
 	}
 	if (!changed)
 		return 0;
-	return slave_put_val(slave, ucontrol);
+	err = slave_put_val(slave, ucontrol);
+	if (err < 0)
+		return err;
+	return 1;
 }
 
 static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
diff -druNp linux-libre-3.8-gnu1/sound/drivers/aloop.c linux-libre-3.8.13-gnu1/sound/drivers/aloop.c
--- linux-libre-3.8-gnu1/sound/drivers/aloop.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/drivers/aloop.c	2013-05-11 16:57:46.000000000 -0400
@@ -286,12 +286,14 @@ static int loopback_trigger(struct snd_p
 			loopback_active_notify(dpcm);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
 		spin_lock(&cable->lock);	
 		cable->pause |= stream;
 		loopback_timer_stop(dpcm);
 		spin_unlock(&cable->lock);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
 		spin_lock(&cable->lock);
 		dpcm->last_jiffies = jiffies;
 		cable->pause &= ~stream;
@@ -563,7 +565,8 @@ static snd_pcm_uframes_t loopback_pointe
 static struct snd_pcm_hardware loopback_pcm_hardware =
 {
 	.info =		(SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
-			 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
+			 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE |
+			 SNDRV_PCM_INFO_RESUME),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
 			 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |
 			 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE),
diff -druNp linux-libre-3.8-gnu1/sound/pci/ali5451/ali5451.c linux-libre-3.8.13-gnu1/sound/pci/ali5451/ali5451.c
--- linux-libre-3.8-gnu1/sound/pci/ali5451/ali5451.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/ali5451/ali5451.c	2013-05-11 16:57:46.000000000 -0400
@@ -1435,7 +1435,7 @@ static snd_pcm_uframes_t snd_ali_pointer
 
 	spin_lock(&codec->reg_lock);
 	if (!pvoice->running) {
-		spin_unlock_irq(&codec->reg_lock);
+		spin_unlock(&codec->reg_lock);
 		return 0;
 	}
 	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
diff -druNp linux-libre-3.8-gnu1/sound/pci/bt87x.c linux-libre-3.8.13-gnu1/sound/pci/bt87x.c
--- linux-libre-3.8-gnu1/sound/pci/bt87x.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/bt87x.c	2013-05-11 16:57:46.000000000 -0400
@@ -836,6 +836,8 @@ static struct {
 	{0x7063, 0x2000}, /* pcHDTV HD-2000 TV */
 };
 
+static struct pci_driver driver;
+
 /* return the id of the card, or a negative value if it's blacklisted */
 static int snd_bt87x_detect_card(struct pci_dev *pci)
 {
@@ -962,11 +964,24 @@ static DEFINE_PCI_DEVICE_TABLE(snd_bt87x
 	{ }
 };
 
-static struct pci_driver bt87x_driver = {
+static struct pci_driver driver = {
 	.name = KBUILD_MODNAME,
 	.id_table = snd_bt87x_ids,
 	.probe = snd_bt87x_probe,
 	.remove = snd_bt87x_remove,
 };
 
-module_pci_driver(bt87x_driver);
+static int __init alsa_card_bt87x_init(void)
+{
+	if (load_all)
+		driver.id_table = snd_bt87x_default_ids;
+	return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_bt87x_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_bt87x_init)
+module_exit(alsa_card_bt87x_exit)
diff -druNp linux-libre-3.8-gnu1/sound/pci/emu10k1/emu10k1_main.c linux-libre-3.8.13-gnu1/sound/pci/emu10k1/emu10k1_main.c
--- linux-libre-3.8-gnu1/sound/pci/emu10k1/emu10k1_main.c	2013-05-01 16:49:48.000000000 -0400
+++ linux-libre-3.8.13-gnu1/sound/pci/emu10k1/emu10k1_main.c	2013-05-11 19:25:36.000000000 -0400
@@ -652,14 +652,14 @@ static int snd_emu10k1_cardbus_init(stru
 	return 0;
 }
 
-static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu,
+				     const struct firmware *fw_entry)
 {
 	int n, i;
 	int reg;
 	int value;
 	unsigned int write_post;
 	unsigned long flags;
-	const struct firmware *fw_entry = emu->firmware;
 
 	if (!fw_entry)
 		return -EIO;
@@ -720,9 +720,34 @@ static int emu1010_firmware_thread(void
 			/* Return to Audio Dock programming mode */
 			snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
 			snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
-			err = snd_emu1010_load_firmware(emu);
-			if (err != 0)
-				continue;
+
+			if (!emu->dock_fw) {
+				const char *filename = NULL;
+				switch (emu->card_capabilities->emu_model) {
+				case EMU_MODEL_EMU1010:
+					filename = DOCK_FILENAME;
+					break;
+				case EMU_MODEL_EMU1010B:
+					filename = MICRO_DOCK_FILENAME;
+					break;
+				case EMU_MODEL_EMU1616:
+					filename = MICRO_DOCK_FILENAME;
+					break;
+				}
+				if (filename) {
+					err = reject_firmware(&emu->dock_fw,
+							       filename,
+							       &emu->pci->dev);
+					if (err)
+						continue;
+				}
+			}
+
+			if (emu->dock_fw) {
+				err = snd_emu1010_load_firmware(emu, emu->dock_fw);
+				if (err)
+					continue;
+			}
 
 			snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
 			snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg);
@@ -857,6 +882,12 @@ static int snd_emu10k1_emu1010_init(stru
 			   filename, emu->firmware->size);
 	}
 
+	err = snd_emu1010_load_firmware(emu, emu->firmware);
+	if (err != 0) {
+		snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n");
+		return err;
+	}
+
 	/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
 	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
 	if ((reg & 0x3f) != 0x15) {
@@ -1242,6 +1273,8 @@ static int snd_emu10k1_free(struct snd_e
 		kthread_stop(emu->emu1010.firmware_thread);
 	if (emu->firmware)
 		release_firmware(emu->firmware);
+	if (emu->dock_fw)
+		release_firmware(emu->dock_fw);
 	if (emu->irq >= 0)
 		free_irq(emu->irq, emu);
 	/* remove reserved page */
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/hda_codec.c linux-libre-3.8.13-gnu1/sound/pci/hda/hda_codec.c
--- linux-libre-3.8-gnu1/sound/pci/hda/hda_codec.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/hda_codec.c	2013-05-11 16:57:46.000000000 -0400
@@ -173,7 +173,7 @@ const char *snd_hda_get_jack_type(u32 cf
 		"Line Out", "Speaker", "HP Out", "CD",
 		"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
 		"Line In", "Aux", "Mic", "Telephony",
-		"SPDIF In", "Digitial In", "Reserved", "Other"
+		"SPDIF In", "Digital In", "Reserved", "Other"
 	};
 
 	return jack_types[(cfg & AC_DEFCFG_DEVICE)
@@ -2160,11 +2160,12 @@ struct snd_kcontrol *snd_hda_find_mixer_
 EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
 
 static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
-				    int dev)
+				    int start_idx)
 {
-	int idx;
-	for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
-		if (!find_mixer_ctl(codec, name, dev, idx))
+	int i, idx;
+	/* 16 ctlrs should be large enough */
+	for (i = 0, idx = start_idx; i < 16; i++, idx++) {
+		if (!find_mixer_ctl(codec, name, 0, idx))
 			return idx;
 	}
 	return -EBUSY;
@@ -2966,7 +2967,7 @@ static unsigned int convert_to_spdif_sta
 	if (val & AC_DIG1_PROFESSIONAL)
 		sbits |= IEC958_AES0_PROFESSIONAL;
 	if (sbits & IEC958_AES0_PROFESSIONAL) {
-		if (sbits & AC_DIG1_EMPHASIS)
+		if (val & AC_DIG1_EMPHASIS)
 			sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
 	} else {
 		if (val & AC_DIG1_EMPHASIS)
@@ -3132,30 +3133,29 @@ int snd_hda_create_dig_out_ctls(struct h
 	int err;
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol_new *dig_mix;
-	int idx, dev = 0;
-	const int spdif_pcm_dev = 1;
+	int idx = 0;
+	const int spdif_index = 16;
 	struct hda_spdif_out *spdif;
+	struct hda_bus *bus = codec->bus;
 
-	if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
+	if (bus->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
 	    type == HDA_PCM_TYPE_SPDIF) {
-		dev = spdif_pcm_dev;
-	} else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
+		idx = spdif_index;
+	} else if (bus->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
 		   type == HDA_PCM_TYPE_HDMI) {
-		for (idx = 0; idx < codec->spdif_out.used; idx++) {
-			spdif = snd_array_elem(&codec->spdif_out, idx);
-			for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
-				kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx);
-				if (!kctl)
-					break;
-				kctl->id.device = spdif_pcm_dev;
-			}
+		/* suppose a single SPDIF device */
+		for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+			kctl = find_mixer_ctl(codec, dig_mix->name, 0, 0);
+			if (!kctl)
+				break;
+			kctl->id.index = spdif_index;
 		}
-		codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
+		bus->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
 	}
-	if (!codec->primary_dig_out_type)
-		codec->primary_dig_out_type = type;
+	if (!bus->primary_dig_out_type)
+		bus->primary_dig_out_type = type;
 
-	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev);
+	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", idx);
 	if (idx < 0) {
 		printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
 		return -EBUSY;
@@ -3165,7 +3165,6 @@ int snd_hda_create_dig_out_ctls(struct h
 		kctl = snd_ctl_new1(dig_mix, codec);
 		if (!kctl)
 			return -ENOMEM;
-		kctl->id.device = dev;
 		kctl->id.index = idx;
 		kctl->private_value = codec->spdif_out.used - 1;
 		err = snd_hda_ctl_add(codec, associated_nid, kctl);
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/hda_codec.h linux-libre-3.8.13-gnu1/sound/pci/hda/hda_codec.h
--- linux-libre-3.8-gnu1/sound/pci/hda/hda_codec.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/hda_codec.h	2013-05-11 16:57:46.000000000 -0400
@@ -671,6 +671,8 @@ struct hda_bus {
 	unsigned int response_reset:1;	/* controller was reset */
 	unsigned int in_reset:1;	/* during reset operation */
 	unsigned int power_keep_link_on:1; /* don't power off HDA link */
+
+	int primary_dig_out_type;	/* primary digital out PCM type */
 };
 
 /*
@@ -837,7 +839,6 @@ struct hda_codec {
 	struct mutex hash_mutex;
 	struct snd_array spdif_out;
 	unsigned int spdif_in_enable;	/* SPDIF input enable? */
-	int primary_dig_out_type;	/* primary digital out PCM type */
 	const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
 	struct snd_array init_pins;	/* initial (BIOS) pin configurations */
 	struct snd_array driver_pins;	/* pin configs set by codec parser */
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/hda_eld.c linux-libre-3.8.13-gnu1/sound/pci/hda/hda_eld.c
--- linux-libre-3.8-gnu1/sound/pci/hda/hda_eld.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/hda_eld.c	2013-05-11 16:57:46.000000000 -0400
@@ -322,7 +322,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *el
 		     struct hda_codec *codec, hda_nid_t nid)
 {
 	int i;
-	int ret;
+	int ret = 0;
 	int size;
 	unsigned char *buf;
 
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/hda_intel.c linux-libre-3.8.13-gnu1/sound/pci/hda/hda_intel.c
--- linux-libre-3.8-gnu1/sound/pci/hda/hda_intel.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/hda_intel.c	2013-05-11 16:57:46.000000000 -0400
@@ -3624,7 +3624,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids)
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
 	/* 5 Series/3400 */
 	{ PCI_DEVICE(0x8086, 0x3b56),
-	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
+	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
 	/* Poulsbo */
 	{ PCI_DEVICE(0x8086, 0x811b),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/patch_conexant.c linux-libre-3.8.13-gnu1/sound/pci/hda/patch_conexant.c
--- linux-libre-3.8-gnu1/sound/pci/hda/patch_conexant.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/patch_conexant.c	2013-05-11 16:57:46.000000000 -0400
@@ -1175,7 +1175,7 @@ static int patch_cxt5045(struct hda_code
 	}
 
 	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, spec->beep_amp);
+		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
 	return 0;
 }
@@ -1954,7 +1954,7 @@ static int patch_cxt5051(struct hda_code
 	}
 
 	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, spec->beep_amp);
+		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
 	return 0;
 }
@@ -3136,7 +3136,7 @@ static int patch_cxt5066(struct hda_code
 	}
 
 	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, spec->beep_amp);
+		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
 	return 0;
 }
@@ -4576,7 +4576,7 @@ static int patch_conexant_auto(struct hd
 	spec->capture_stream = &cx_auto_pcm_analog_capture;
 	codec->patch_ops = cx_auto_patch_ops;
 	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, spec->beep_amp);
+		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
 	/* Some laptops with Conexant chips show stalls in S3 resume,
 	 * which falls into the single-cmd mode.
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/patch_hdmi.c linux-libre-3.8.13-gnu1/sound/pci/hda/patch_hdmi.c
--- linux-libre-3.8-gnu1/sound/pci/hda/patch_hdmi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/patch_hdmi.c	2013-05-11 16:57:46.000000000 -0400
@@ -714,9 +714,10 @@ static void hdmi_setup_fake_chmap(unsign
 
 static void hdmi_setup_channel_mapping(struct hda_codec *codec,
 				       hda_nid_t pin_nid, bool non_pcm, int ca,
-				       int channels, unsigned char *map)
+				       int channels, unsigned char *map,
+				       bool chmap_set)
 {
-	if (!non_pcm && map) {
+	if (!non_pcm && chmap_set) {
 		hdmi_manual_setup_channel_mapping(codec, pin_nid,
 						  channels, map);
 	} else {
@@ -905,7 +906,8 @@ static void hdmi_setup_audio_infoframe(s
 			    pin_nid,
 			    channels);
 		hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
-					   channels, per_pin->chmap);
+					   channels, per_pin->chmap,
+					   per_pin->chmap_set);
 		hdmi_stop_infoframe_trans(codec, pin_nid);
 		hdmi_fill_audio_infoframe(codec, pin_nid,
 					    ai.bytes, sizeof(ai));
@@ -915,7 +917,8 @@ static void hdmi_setup_audio_infoframe(s
 		 * accordingly */
 		if (per_pin->non_pcm != non_pcm)
 			hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
-						   channels, per_pin->chmap);
+						   channels, per_pin->chmap,
+						   per_pin->chmap_set);
 	}
 
 	per_pin->non_pcm = non_pcm;
@@ -1100,8 +1103,12 @@ static int hdmi_pcm_open(struct hda_pcm_
 	if (!static_hdmi_pcm && eld->eld_valid) {
 		snd_hdmi_eld_update_pcm_info(eld, hinfo);
 		if (hinfo->channels_min > hinfo->channels_max ||
-		    !hinfo->rates || !hinfo->formats)
+		    !hinfo->rates || !hinfo->formats) {
+			per_cvt->assigned = 0;
+			hinfo->nid = 0;
+			snd_hda_spdif_ctls_unassign(codec, pin_idx);
 			return -ENODEV;
+		}
 	}
 
 	/* Store the updated parameters */
@@ -1165,6 +1172,7 @@ static void hdmi_present_sense(struct hd
 		"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
 		codec->addr, pin_nid, eld->monitor_present, eld_valid);
 
+	eld->eld_valid = false;
 	if (eld_valid) {
 		if (!snd_hdmi_get_eld(eld, codec, pin_nid))
 			snd_hdmi_show_eld(eld);
@@ -1565,6 +1573,9 @@ static int generic_hdmi_build_jack(struc
 
 	if (pcmdev > 0)
 		sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
+	if (!is_jack_detectable(codec, per_pin->pin_nid))
+		strncat(hdmi_str, " Phantom",
+			sizeof(hdmi_str) - strlen(hdmi_str) - 1);
 
 	return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0);
 }
diff -druNp linux-libre-3.8-gnu1/sound/pci/hda/patch_realtek.c linux-libre-3.8.13-gnu1/sound/pci/hda/patch_realtek.c
--- linux-libre-3.8-gnu1/sound/pci/hda/patch_realtek.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/hda/patch_realtek.c	2013-05-11 16:57:46.000000000 -0400
@@ -5394,6 +5394,7 @@ static const struct snd_pci_quirk alc882
 	SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
 	SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
 	SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
+	SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
 
 	/* All Apple entries are in codec SSIDs */
 	SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
@@ -5822,6 +5823,7 @@ enum {
 	ALC269_TYPE_ALC280,
 	ALC269_TYPE_ALC282,
 	ALC269_TYPE_ALC284,
+	ALC269_TYPE_ALC286,
 };
 
 /*
@@ -5845,6 +5847,7 @@ static int alc269_parse_auto_config(stru
 	case ALC269_TYPE_ALC269VB:
 	case ALC269_TYPE_ALC269VD:
 	case ALC269_TYPE_ALC282:
+	case ALC269_TYPE_ALC286:
 		ssids = alc269_ssids;
 		break;
 	default:
@@ -6450,6 +6453,9 @@ static int patch_alc269(struct hda_codec
 	case 0x10ec0292:
 		spec->codec_variant = ALC269_TYPE_ALC284;
 		break;
+	case 0x10ec0286:
+		spec->codec_variant = ALC269_TYPE_ALC286;
+		break;
 	}
 
 	/* automatic parse from the BIOS config */
@@ -6719,7 +6725,8 @@ static int alc662_parse_auto_config(stru
 	const hda_nid_t *ssids;
 
 	if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
-	    codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
+	    codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
+	    codec->vendor_id == 0x10ec0671)
 		ssids = alc663_ssids;
 	else
 		ssids = alc662_ssids;
@@ -7155,6 +7162,7 @@ static const struct hda_codec_preset snd
 	{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
 	{ .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
 	{ .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
+	{ .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
 	{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
 	{ .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
 	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
@@ -7172,6 +7180,7 @@ static const struct hda_codec_preset snd
 	{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
 	{ .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
 	{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
+	{ .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
 	{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
diff -druNp linux-libre-3.8-gnu1/sound/pci/ice1712/ice1712.c linux-libre-3.8.13-gnu1/sound/pci/ice1712/ice1712.c
--- linux-libre-3.8-gnu1/sound/pci/ice1712/ice1712.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/ice1712/ice1712.c	2013-05-11 16:57:46.000000000 -0400
@@ -2594,6 +2594,8 @@ static int snd_ice1712_create(struct snd
 	snd_ice1712_proc_init(ice);
 	synchronize_irq(pci->irq);
 
+	card->private_data = ice;
+
 	err = pci_request_regions(pci, "ICE1712");
 	if (err < 0) {
 		kfree(ice);
diff -druNp linux-libre-3.8-gnu1/sound/pci/rme32.c linux-libre-3.8.13-gnu1/sound/pci/rme32.c
--- linux-libre-3.8-gnu1/sound/pci/rme32.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/pci/rme32.c	2013-05-11 16:57:46.000000000 -0400
@@ -1017,7 +1017,7 @@ static int snd_rme32_capture_close(struc
 	spin_lock_irq(&rme32->lock);
 	rme32->capture_substream = NULL;
 	rme32->capture_periodsize = 0;
-	spin_unlock(&rme32->lock);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 
diff -druNp linux-libre-3.8-gnu1/sound/soc/codecs/arizona.c linux-libre-3.8.13-gnu1/sound/soc/codecs/arizona.c
--- linux-libre-3.8-gnu1/sound/soc/codecs/arizona.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/codecs/arizona.c	2013-05-11 16:57:46.000000000 -0400
@@ -910,7 +910,7 @@ static int arizona_calc_fll(struct arizo
 
 	cfg->n = target / (ratio * Fref);
 
-	if (target % Fref) {
+	if (target % (ratio * Fref)) {
 		gcd_fll = gcd(target, ratio * Fref);
 		arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
 
@@ -922,6 +922,15 @@ static int arizona_calc_fll(struct arizo
 		cfg->lambda = 0;
 	}
 
+	/* Round down to 16bit range with cost of accuracy lost.
+	 * Denominator must be bigger than numerator so we only
+	 * take care of it.
+	 */
+	while (cfg->lambda >= (1 << 16)) {
+		cfg->theta >>= 1;
+		cfg->lambda >>= 1;
+	}
+
 	arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
 			cfg->n, cfg->theta, cfg->lambda);
 	arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
diff -druNp linux-libre-3.8-gnu1/sound/soc/codecs/max98088.c linux-libre-3.8.13-gnu1/sound/soc/codecs/max98088.c
--- linux-libre-3.8-gnu1/sound/soc/codecs/max98088.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/codecs/max98088.c	2013-05-11 16:57:46.000000000 -0400
@@ -2006,7 +2006,7 @@ static int max98088_probe(struct snd_soc
                        ret);
                goto err_access;
        }
-       dev_info(codec->dev, "revision %c\n", ret + 'A');
+       dev_info(codec->dev, "revision %c\n", ret - 0x40 + 'A');
 
        snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV);
 
diff -druNp linux-libre-3.8-gnu1/sound/soc/codecs/wm2200.c linux-libre-3.8.13-gnu1/sound/soc/codecs/wm2200.c
--- linux-libre-3.8-gnu1/sound/soc/codecs/wm2200.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/codecs/wm2200.c	2013-05-11 16:57:46.000000000 -0400
@@ -1126,9 +1126,9 @@ SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN
 
 SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
 	     WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
-SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_2L,
 	     WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
-SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_3L,
 	     WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
 
 SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
diff -druNp linux-libre-3.8-gnu1/sound/soc/codecs/wm5102.c linux-libre-3.8.13-gnu1/sound/soc/codecs/wm5102.c
--- linux-libre-3.8-gnu1/sound/soc/codecs/wm5102.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/codecs/wm5102.c	2013-05-11 16:57:46.000000000 -0400
@@ -576,7 +576,7 @@ static int wm5102_sysclk_ev(struct snd_s
 			    struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	struct arizona *arizona = dev_get_drvdata(codec->dev);
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
 	struct regmap *regmap = codec->control_data;
 	const struct reg_default *patch = NULL;
 	int i, patch_size;
diff -druNp linux-libre-3.8-gnu1/sound/soc/codecs/wm8903.c linux-libre-3.8.13-gnu1/sound/soc/codecs/wm8903.c
--- linux-libre-3.8-gnu1/sound/soc/codecs/wm8903.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/codecs/wm8903.c	2013-05-11 16:57:46.000000000 -0400
@@ -1083,6 +1083,8 @@ static const struct snd_soc_dapm_route w
 	{ "ROP", NULL, "Right Speaker PGA" },
 	{ "RON", NULL, "Right Speaker PGA" },
 
+	{ "Charge Pump", NULL, "CLK_DSP" },
+
 	{ "Left Headphone Output PGA", NULL, "Charge Pump" },
 	{ "Right Headphone Output PGA", NULL, "Charge Pump" },
 	{ "Left Line Output PGA", NULL, "Charge Pump" },
diff -druNp linux-libre-3.8-gnu1/sound/soc/fsl/imx-ssi.c linux-libre-3.8.13-gnu1/sound/soc/fsl/imx-ssi.c
--- linux-libre-3.8-gnu1/sound/soc/fsl/imx-ssi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/fsl/imx-ssi.c	2013-05-11 16:57:46.000000000 -0400
@@ -496,6 +496,8 @@ static void imx_ssi_ac97_reset(struct sn
 
 	if (imx_ssi->ac97_reset)
 		imx_ssi->ac97_reset(ac97);
+	/* First read sometimes fails, do a dummy read */
+	imx_ssi_ac97_read(ac97, 0);
 }
 
 static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -504,6 +506,9 @@ static void imx_ssi_ac97_warm_reset(stru
 
 	if (imx_ssi->ac97_warm_reset)
 		imx_ssi->ac97_warm_reset(ac97);
+
+	/* First read sometimes fails, do a dummy read */
+	imx_ssi_ac97_read(ac97, 0);
 }
 
 struct snd_ac97_bus_ops soc_ac97_ops = {
diff -druNp linux-libre-3.8-gnu1/sound/soc/sh/dma-sh7760.c linux-libre-3.8.13-gnu1/sound/soc/sh/dma-sh7760.c
--- linux-libre-3.8-gnu1/sound/soc/sh/dma-sh7760.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/sh/dma-sh7760.c	2013-05-11 16:57:46.000000000 -0400
@@ -342,8 +342,8 @@ static int camelot_pcm_new(struct snd_so
 	return 0;
 }
 
-static struct snd_soc_platform sh7760_soc_platform = {
-	.pcm_ops 	= &camelot_pcm_ops,
+static struct snd_soc_platform_driver sh7760_soc_platform = {
+	.ops		= &camelot_pcm_ops,
 	.pcm_new	= camelot_pcm_new,
 	.pcm_free	= camelot_pcm_free,
 };
diff -druNp linux-libre-3.8-gnu1/sound/soc/soc-core.c linux-libre-3.8.13-gnu1/sound/soc/soc-core.c
--- linux-libre-3.8-gnu1/sound/soc/soc-core.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/soc-core.c	2013-05-11 16:57:46.000000000 -0400
@@ -2959,7 +2959,7 @@ int snd_soc_put_volsw_range(struct snd_k
 	val = val << shift;
 
 	ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
-	if (ret != 0)
+	if (ret < 0)
 		return ret;
 
 	if (snd_soc_volsw_is_stereo(mc)) {
diff -druNp linux-libre-3.8-gnu1/sound/soc/spear/spear_pcm.c linux-libre-3.8.13-gnu1/sound/soc/spear/spear_pcm.c
--- linux-libre-3.8-gnu1/sound/soc/spear/spear_pcm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/soc/spear/spear_pcm.c	2013-05-11 16:57:46.000000000 -0400
@@ -149,9 +149,9 @@ static void spear_pcm_free(struct snd_pc
 
 static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int spear_pcm_new(struct snd_card *card,
-		struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
 	int ret;
 
 	if (!card->dev->dma_mask)
@@ -159,16 +159,16 @@ static int spear_pcm_new(struct snd_card
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-	if (dai->driver->playback.channels_min) {
-		ret = spear_pcm_preallocate_dma_buffer(pcm,
+	if (rtd->cpu_dai->driver->playback.channels_min) {
+		ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
 				SNDRV_PCM_STREAM_PLAYBACK,
 				spear_pcm_hardware.buffer_bytes_max);
 		if (ret)
 			return ret;
 	}
 
-	if (dai->driver->capture.channels_min) {
-		ret = spear_pcm_preallocate_dma_buffer(pcm,
+	if (rtd->cpu_dai->driver->capture.channels_min) {
+		ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
 				SNDRV_PCM_STREAM_CAPTURE,
 				spear_pcm_hardware.buffer_bytes_max);
 		if (ret)
diff -druNp linux-libre-3.8-gnu1/sound/usb/6fire/pcm.c linux-libre-3.8.13-gnu1/sound/usb/6fire/pcm.c
--- linux-libre-3.8-gnu1/sound/usb/6fire/pcm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/6fire/pcm.c	2013-05-11 16:57:46.000000000 -0400
@@ -575,7 +575,6 @@ static void usb6fire_pcm_init_urb(struct
 	urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep)
 			: usb_sndisocpipe(chip->dev, ep);
 	urb->instance.interval = 1;
-	urb->instance.transfer_flags = URB_ISO_ASAP;
 	urb->instance.complete = handler;
 	urb->instance.context = urb;
 	urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
diff -druNp linux-libre-3.8-gnu1/sound/usb/caiaq/audio.c linux-libre-3.8.13-gnu1/sound/usb/caiaq/audio.c
--- linux-libre-3.8-gnu1/sound/usb/caiaq/audio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/caiaq/audio.c	2013-05-11 16:57:46.000000000 -0400
@@ -670,7 +670,6 @@ static void read_completed(struct urb *u
 
 	if (send_it) {
 		out->number_of_packets = outframe;
-		out->transfer_flags = URB_ISO_ASAP;
 		usb_submit_urb(out, GFP_ATOMIC);
 	} else {
 		struct snd_usb_caiaq_cb_info *oinfo = out->context;
@@ -686,7 +685,6 @@ requeue:
 	}
 
 	urb->number_of_packets = FRAMES_PER_URB;
-	urb->transfer_flags = URB_ISO_ASAP;
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
@@ -751,7 +749,6 @@ static struct urb **alloc_urbs(struct sn
 						* BYTES_PER_FRAME;
 		urbs[i]->context = &dev->data_cb_info[i];
 		urbs[i]->interval = 1;
-		urbs[i]->transfer_flags = URB_ISO_ASAP;
 		urbs[i]->number_of_packets = FRAMES_PER_URB;
 		urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ?
 					read_completed : write_completed;
diff -druNp linux-libre-3.8-gnu1/sound/usb/card.c linux-libre-3.8.13-gnu1/sound/usb/card.c
--- linux-libre-3.8-gnu1/sound/usb/card.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/card.c	2013-05-11 16:57:46.000000000 -0400
@@ -612,7 +612,9 @@ int snd_usb_autoresume(struct snd_usb_au
 	int err = -ENODEV;
 
 	down_read(&chip->shutdown_rwsem);
-	if (!chip->shutdown && !chip->probing)
+	if (chip->probing)
+		err = 0;
+	else if (!chip->shutdown)
 		err = usb_autopm_get_interface(chip->pm_intf);
 	up_read(&chip->shutdown_rwsem);
 
diff -druNp linux-libre-3.8-gnu1/sound/usb/card.h linux-libre-3.8.13-gnu1/sound/usb/card.h
--- linux-libre-3.8-gnu1/sound/usb/card.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/card.h	2013-05-11 16:57:46.000000000 -0400
@@ -116,6 +116,7 @@ struct snd_usb_substream {
 	unsigned int altset_idx;     /* USB data format: index of alternate setting */
 	unsigned int txfr_quirk:1;	/* allow sub-frame alignment */
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
+	unsigned int pkt_offset_adj;	/* Bytes to drop from beginning of packets (for non-compliant devices) */
 
 	unsigned int running: 1;	/* running status */
 
diff -druNp linux-libre-3.8-gnu1/sound/usb/endpoint.c linux-libre-3.8.13-gnu1/sound/usb/endpoint.c
--- linux-libre-3.8-gnu1/sound/usb/endpoint.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/endpoint.c	2013-05-11 16:57:46.000000000 -0400
@@ -677,7 +677,7 @@ static int data_ep_set_params(struct snd
 		if (!u->urb->transfer_buffer)
 			goto out_of_memory;
 		u->urb->pipe = ep->pipe;
-		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		u->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 		u->urb->interval = 1 << ep->datainterval;
 		u->urb->context = u;
 		u->urb->complete = snd_complete_urb;
@@ -716,8 +716,7 @@ static int sync_ep_set_params(struct snd
 		u->urb->transfer_dma = ep->sync_dma + i * 4;
 		u->urb->transfer_buffer_length = 4;
 		u->urb->pipe = ep->pipe;
-		u->urb->transfer_flags = URB_ISO_ASAP |
-					 URB_NO_TRANSFER_DMA_MAP;
+		u->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 		u->urb->number_of_packets = 1;
 		u->urb->interval = 1 << ep->syncinterval;
 		u->urb->context = u;
diff -druNp linux-libre-3.8-gnu1/sound/usb/midi.c linux-libre-3.8.13-gnu1/sound/usb/midi.c
--- linux-libre-3.8-gnu1/sound/usb/midi.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/midi.c	2013-05-11 16:57:46.000000000 -0400
@@ -126,7 +126,6 @@ struct snd_usb_midi {
 		struct snd_usb_midi_in_endpoint *in;
 	} endpoints[MIDI_MAX_ENDPOINTS];
 	unsigned long input_triggered;
-	bool autopm_reference;
 	unsigned int opened[2];
 	unsigned char disconnected;
 	unsigned char input_running;
@@ -1040,7 +1039,6 @@ static int substream_open(struct snd_raw
 {
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
 	struct snd_kcontrol *ctl;
-	int err;
 
 	down_read(&umidi->disc_rwsem);
 	if (umidi->disconnected) {
@@ -1051,13 +1049,6 @@ static int substream_open(struct snd_raw
 	mutex_lock(&umidi->mutex);
 	if (open) {
 		if (!umidi->opened[0] && !umidi->opened[1]) {
-			err = usb_autopm_get_interface(umidi->iface);
-			umidi->autopm_reference = err >= 0;
-			if (err < 0 && err != -EACCES) {
-				mutex_unlock(&umidi->mutex);
-				up_read(&umidi->disc_rwsem);
-				return -EIO;
-			}
 			if (umidi->roland_load_ctl) {
 				ctl = umidi->roland_load_ctl;
 				ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -1080,8 +1071,6 @@ static int substream_open(struct snd_raw
 				snd_ctl_notify(umidi->card,
 				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
 			}
-			if (umidi->autopm_reference)
-				usb_autopm_put_interface(umidi->iface);
 		}
 	}
 	mutex_unlock(&umidi->mutex);
@@ -2256,6 +2245,8 @@ int snd_usbmidi_create(struct snd_card *
 		return err;
 	}
 
+	usb_autopm_get_interface_no_resume(umidi->iface);
+
 	list_add_tail(&umidi->list, midi_list);
 	return 0;
 }
diff -druNp linux-libre-3.8-gnu1/sound/usb/misc/ua101.c linux-libre-3.8.13-gnu1/sound/usb/misc/ua101.c
--- linux-libre-3.8-gnu1/sound/usb/misc/ua101.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/misc/ua101.c	2013-05-11 16:57:46.000000000 -0400
@@ -1120,8 +1120,7 @@ static int alloc_stream_urbs(struct ua10
 			usb_init_urb(&urb->urb);
 			urb->urb.dev = ua->dev;
 			urb->urb.pipe = stream->usb_pipe;
-			urb->urb.transfer_flags = URB_ISO_ASAP |
-					URB_NO_TRANSFER_DMA_MAP;
+			urb->urb.transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 			urb->urb.transfer_buffer = addr;
 			urb->urb.transfer_dma = dma;
 			urb->urb.transfer_buffer_length = max_packet_size;
diff -druNp linux-libre-3.8-gnu1/sound/usb/mixer.c linux-libre-3.8.13-gnu1/sound/usb/mixer.c
--- linux-libre-3.8-gnu1/sound/usb/mixer.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/mixer.c	2013-05-11 16:57:46.000000000 -0400
@@ -715,8 +715,9 @@ static int check_input_term(struct mixer
 		case UAC2_CLOCK_SELECTOR: {
 			struct uac_selector_unit_descriptor *d = p1;
 			/* call recursively to retrieve the channel info */
-			if (check_input_term(state, d->baSourceID[0], term) < 0)
-				return -ENODEV;
+			err = check_input_term(state, d->baSourceID[0], term);
+			if (err < 0)
+				return err;
 			term->type = d->bDescriptorSubtype << 16; /* virtual type */
 			term->id = id;
 			term->name = uac_selector_unit_iSelector(d);
@@ -725,7 +726,8 @@ static int check_input_term(struct mixer
 		case UAC1_PROCESSING_UNIT:
 		case UAC1_EXTENSION_UNIT:
 		/* UAC2_PROCESSING_UNIT_V2 */
-		/* UAC2_EFFECT_UNIT */ {
+		/* UAC2_EFFECT_UNIT */
+		case UAC2_EXTENSION_UNIT_V2: {
 			struct uac_processing_unit_descriptor *d = p1;
 
 			if (state->mixer->protocol == UAC_VERSION_2 &&
@@ -1355,8 +1357,9 @@ static int parse_audio_feature_unit(stru
 		return err;
 
 	/* determine the input source type and name */
-	if (check_input_term(state, hdr->bSourceID, &iterm) < 0)
-		return -EINVAL;
+	err = check_input_term(state, hdr->bSourceID, &iterm);
+	if (err < 0)
+		return err;
 
 	master_bits = snd_usb_combine_bytes(bmaControls, csize);
 	/* master configuration quirks */
@@ -2051,6 +2054,8 @@ static int parse_audio_unit(struct mixer
 			return parse_audio_extension_unit(state, unitid, p1);
 		else /* UAC_VERSION_2 */
 			return parse_audio_processing_unit(state, unitid, p1);
+	case UAC2_EXTENSION_UNIT_V2:
+		return parse_audio_extension_unit(state, unitid, p1);
 	default:
 		snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
 		return -EINVAL;
@@ -2117,7 +2122,7 @@ static int snd_usb_mixer_controls(struct
 			state.oterm.type = le16_to_cpu(desc->wTerminalType);
 			state.oterm.name = desc->iTerminal;
 			err = parse_audio_unit(&state, desc->bSourceID);
-			if (err < 0)
+			if (err < 0 && err != -EINVAL)
 				return err;
 		} else { /* UAC_VERSION_2 */
 			struct uac2_output_terminal_descriptor *desc = p;
@@ -2129,12 +2134,12 @@ static int snd_usb_mixer_controls(struct
 			state.oterm.type = le16_to_cpu(desc->wTerminalType);
 			state.oterm.name = desc->iTerminal;
 			err = parse_audio_unit(&state, desc->bSourceID);
-			if (err < 0)
+			if (err < 0 && err != -EINVAL)
 				return err;
 
 			/* for UAC2, use the same approach to also add the clock selectors */
 			err = parse_audio_unit(&state, desc->bCSourceID);
-			if (err < 0)
+			if (err < 0 && err != -EINVAL)
 				return err;
 		}
 	}
diff -druNp linux-libre-3.8-gnu1/sound/usb/mixer_quirks.c linux-libre-3.8.13-gnu1/sound/usb/mixer_quirks.c
--- linux-libre-3.8-gnu1/sound/usb/mixer_quirks.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/mixer_quirks.c	2013-05-11 16:57:46.000000000 -0400
@@ -509,7 +509,7 @@ static int snd_nativeinstruments_control
 	else
 		ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
 				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-				  0, cpu_to_le16(wIndex),
+				  0, wIndex,
 				  &tmp, sizeof(tmp), 1000);
 	up_read(&mixer->chip->shutdown_rwsem);
 
@@ -540,7 +540,7 @@ static int snd_nativeinstruments_control
 	else
 		ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
 				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-				  cpu_to_le16(wValue), cpu_to_le16(wIndex),
+				  wValue, wIndex,
 				  NULL, 0, 1000);
 	up_read(&mixer->chip->shutdown_rwsem);
 
diff -druNp linux-libre-3.8-gnu1/sound/usb/pcm.c linux-libre-3.8.13-gnu1/sound/usb/pcm.c
--- linux-libre-3.8-gnu1/sound/usb/pcm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/pcm.c	2013-05-11 16:57:46.000000000 -0400
@@ -1161,7 +1161,7 @@ static void retire_capture_urb(struct sn
 	stride = runtime->frame_bits >> 3;
 
 	for (i = 0; i < urb->number_of_packets; i++) {
-		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset + subs->pkt_offset_adj;
 		if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
 			snd_printdd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
 			// continue;
diff -druNp linux-libre-3.8-gnu1/sound/usb/quirks.c linux-libre-3.8.13-gnu1/sound/usb/quirks.c
--- linux-libre-3.8-gnu1/sound/usb/quirks.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/quirks.c	2013-05-11 16:57:46.000000000 -0400
@@ -486,7 +486,7 @@ static int snd_usb_nativeinstruments_boo
 {
 	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				  0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				  cpu_to_le16(1), 0, NULL, 0, 1000);
+				  1, 0, NULL, 0, 1000);
 
 	if (ret < 0)
 		return ret;
@@ -533,7 +533,7 @@ static int snd_usb_mbox2_boot_quirk(stru
 {
 	struct usb_host_config *config = dev->actconfig;
 	int err;
-	u8 bootresponse[12];
+	u8 bootresponse[0x12];
 	int fwsize;
 	int count;
 
@@ -837,6 +837,7 @@ static void set_format_emu_quirk(struct
 		break;
 	}
 	snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id);
+	subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
 }
 
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
diff -druNp linux-libre-3.8-gnu1/sound/usb/quirks-table.h linux-libre-3.8.13-gnu1/sound/usb/quirks-table.h
--- linux-libre-3.8-gnu1/sound/usb/quirks-table.h	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/quirks-table.h	2013-05-11 16:57:46.000000000 -0400
@@ -1750,7 +1750,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
 		/* .vendor_name = "Roland", */
 		/* .product_name = "A-PRO", */
-		.ifnum = 1,
+		.ifnum = 0,
 		.type = QUIRK_MIDI_FIXED_ENDPOINT,
 		.data = & (const struct snd_usb_midi_endpoint_info) {
 			.out_cables = 0x0003,
diff -druNp linux-libre-3.8-gnu1/sound/usb/stream.c linux-libre-3.8.13-gnu1/sound/usb/stream.c
--- linux-libre-3.8-gnu1/sound/usb/stream.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/stream.c	2013-05-11 16:57:46.000000000 -0400
@@ -94,6 +94,7 @@ static void snd_usb_init_substream(struc
 	subs->dev = as->chip->dev;
 	subs->txfr_quirk = as->chip->txfr_quirk;
 	subs->speed = snd_usb_get_speed(subs->dev);
+	subs->pkt_offset_adj = 0;
 
 	snd_usb_set_pcm_ops(as->pcm, stream);
 
@@ -396,6 +397,14 @@ static int parse_uac_endpoint_attributes
 	if (!csep && altsd->bNumEndpoints >= 2)
 		csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
 
+	/*
+	 * If we can't locate the USB_DT_CS_ENDPOINT descriptor in the extra
+	 * bytes after the first endpoint, go search the entire interface.
+	 * Some devices have it directly *before* the standard endpoint.
+	 */
+	if (!csep)
+		csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
+
 	if (!csep || csep->bLength < 7 ||
 	    csep->bDescriptorSubtype != UAC_EP_GENERAL) {
 		snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
diff -druNp linux-libre-3.8-gnu1/sound/usb/usx2y/usb_stream.c linux-libre-3.8.13-gnu1/sound/usb/usx2y/usb_stream.c
--- linux-libre-3.8-gnu1/sound/usb/usx2y/usb_stream.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/usx2y/usb_stream.c	2013-05-11 16:57:46.000000000 -0400
@@ -69,7 +69,6 @@ static void init_pipe_urbs(struct usb_st
 	     ++u, transfer += transfer_length) {
 		struct urb *urb = urbs[u];
 		struct usb_iso_packet_descriptor *desc;
-		urb->transfer_flags = URB_ISO_ASAP;
 		urb->transfer_buffer = transfer;
 		urb->dev = dev;
 		urb->pipe = pipe;
diff -druNp linux-libre-3.8-gnu1/sound/usb/usx2y/usbusx2yaudio.c linux-libre-3.8.13-gnu1/sound/usb/usx2y/usbusx2yaudio.c
--- linux-libre-3.8-gnu1/sound/usb/usx2y/usbusx2yaudio.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/usx2y/usbusx2yaudio.c	2013-05-11 16:57:46.000000000 -0400
@@ -503,7 +503,6 @@ static int usX2Y_urbs_start(struct snd_u
 			if (0 == i)
 				atomic_set(&subs->state, state_STARTING3);
 			urb->dev = usX2Y->dev;
-			urb->transfer_flags = URB_ISO_ASAP;
 			for (pack = 0; pack < nr_of_packs(); pack++) {
 				urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
 				urb->iso_frame_desc[pack].length = subs->maxpacksize;
diff -druNp linux-libre-3.8-gnu1/sound/usb/usx2y/usx2yhwdeppcm.c linux-libre-3.8.13-gnu1/sound/usb/usx2y/usx2yhwdeppcm.c
--- linux-libre-3.8-gnu1/sound/usb/usx2y/usx2yhwdeppcm.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/sound/usb/usx2y/usx2yhwdeppcm.c	2013-05-11 16:57:46.000000000 -0400
@@ -443,7 +443,6 @@ static int usX2Y_usbpcm_urbs_start(struc
 					if (0 == u)
 						atomic_set(&subs->state, state_STARTING3);
 					urb->dev = usX2Y->dev;
-					urb->transfer_flags = URB_ISO_ASAP;
 					for (pack = 0; pack < nr_of_packs(); pack++) {
 						urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs());
 						urb->iso_frame_desc[pack].length = subs->maxpacksize;
diff -druNp linux-libre-3.8-gnu1/tools/perf/Makefile linux-libre-3.8.13-gnu1/tools/perf/Makefile
--- linux-libre-3.8-gnu1/tools/perf/Makefile	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/tools/perf/Makefile	2013-05-11 16:57:46.000000000 -0400
@@ -276,13 +276,13 @@ $(OUTPUT)util/parse-events-flex.c: util/
 	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
 
 $(OUTPUT)util/parse-events-bison.c: util/parse-events.y
-	$(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c
+	$(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
 
 $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
 	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
 
 $(OUTPUT)util/pmu-bison.c: util/pmu.y
-	$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
+	$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
 
 $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
 $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
diff -druNp linux-libre-3.8-gnu1/tools/perf/ui/hist.c linux-libre-3.8.13-gnu1/tools/perf/ui/hist.c
--- linux-libre-3.8-gnu1/tools/perf/ui/hist.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/tools/perf/ui/hist.c	2013-05-11 16:57:46.000000000 -0400
@@ -463,11 +463,15 @@ int hist_entry__period_snprintf(struct p
 		if (!perf_hpp__format[i].cond)
 			continue;
 
+		/*
+		 * If there's no field_sep, we still need
+		 * to display initial '  '.
+		 */
 		if (!sep || !first) {
 			ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
 			advance_hpp(hpp, ret);
+		} else
 			first = false;
-		}
 
 		if (color && perf_hpp__format[i].color)
 			ret = perf_hpp__format[i].color(hpp, he);
diff -druNp linux-libre-3.8-gnu1/tools/perf/util/parse-events.y linux-libre-3.8.13-gnu1/tools/perf/util/parse-events.y
--- linux-libre-3.8-gnu1/tools/perf/util/parse-events.y	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/tools/perf/util/parse-events.y	2013-05-11 16:57:46.000000000 -0400
@@ -1,5 +1,4 @@
 %pure-parser
-%name-prefix "parse_events_"
 %parse-param {void *_data}
 %parse-param {void *scanner}
 %lex-param {void* scanner}
diff -druNp linux-libre-3.8-gnu1/tools/perf/util/pmu.y linux-libre-3.8.13-gnu1/tools/perf/util/pmu.y
--- linux-libre-3.8-gnu1/tools/perf/util/pmu.y	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/tools/perf/util/pmu.y	2013-05-11 16:57:46.000000000 -0400
@@ -1,5 +1,4 @@
 
-%name-prefix "perf_pmu_"
 %parse-param {struct list_head *format}
 %parse-param {char *name}
 
diff -druNp linux-libre-3.8-gnu1/tools/usb/ffs-test.c linux-libre-3.8.13-gnu1/tools/usb/ffs-test.c
--- linux-libre-3.8-gnu1/tools/usb/ffs-test.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/tools/usb/ffs-test.c	2013-05-11 16:57:46.000000000 -0400
@@ -38,7 +38,7 @@
 #include <unistd.h>
 #include <tools/le_byteshift.h>
 
-#include "../../include/linux/usb/functionfs.h"
+#include "../../include/uapi/linux/usb/functionfs.h"
 
 
 /******************** Little Endian Handling ********************************/
diff -druNp linux-libre-3.8-gnu1/virt/kvm/ioapic.c linux-libre-3.8.13-gnu1/virt/kvm/ioapic.c
--- linux-libre-3.8-gnu1/virt/kvm/ioapic.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/virt/kvm/ioapic.c	2013-05-11 16:57:46.000000000 -0400
@@ -73,9 +73,12 @@ static unsigned long ioapic_read_indirec
 			u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
 			u64 redir_content;
 
-			ASSERT(redir_index < IOAPIC_NUM_PINS);
+			if (redir_index < IOAPIC_NUM_PINS)
+				redir_content =
+					ioapic->redirtbl[redir_index].bits;
+			else
+				redir_content = ~0ULL;
 
-			redir_content = ioapic->redirtbl[redir_index].bits;
 			result = (ioapic->ioregsel & 0x1) ?
 			    (redir_content >> 32) & 0xffffffff :
 			    redir_content & 0xffffffff;
diff -druNp linux-libre-3.8-gnu1/virt/kvm/kvm_main.c linux-libre-3.8.13-gnu1/virt/kvm/kvm_main.c
--- linux-libre-3.8-gnu1/virt/kvm/kvm_main.c	2013-02-18 18:58:34.000000000 -0500
+++ linux-libre-3.8.13-gnu1/virt/kvm/kvm_main.c	2013-05-11 16:57:46.000000000 -0400
@@ -1476,21 +1476,38 @@ int kvm_write_guest(struct kvm *kvm, gpa
 }
 
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-			      gpa_t gpa)
+			      gpa_t gpa, unsigned long len)
 {
 	struct kvm_memslots *slots = kvm_memslots(kvm);
 	int offset = offset_in_page(gpa);
-	gfn_t gfn = gpa >> PAGE_SHIFT;
+	gfn_t start_gfn = gpa >> PAGE_SHIFT;
+	gfn_t end_gfn = (gpa + len - 1) >> PAGE_SHIFT;
+	gfn_t nr_pages_needed = end_gfn - start_gfn + 1;
+	gfn_t nr_pages_avail;
 
 	ghc->gpa = gpa;
 	ghc->generation = slots->generation;
-	ghc->memslot = gfn_to_memslot(kvm, gfn);
-	ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL);
-	if (!kvm_is_error_hva(ghc->hva))
+	ghc->len = len;
+	ghc->memslot = gfn_to_memslot(kvm, start_gfn);
+	ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
+	if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
 		ghc->hva += offset;
-	else
-		return -EFAULT;
-
+	} else {
+		/*
+		 * If the requested region crosses two memslots, we still
+		 * verify that the entire region is valid here.
+		 */
+		while (start_gfn <= end_gfn) {
+			ghc->memslot = gfn_to_memslot(kvm, start_gfn);
+			ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn,
+						   &nr_pages_avail);
+			if (kvm_is_error_hva(ghc->hva))
+				return -EFAULT;
+			start_gfn += nr_pages_avail;
+		}
+		/* Use the slow path for cross page reads and writes. */
+		ghc->memslot = NULL;
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
@@ -1501,8 +1518,13 @@ int kvm_write_guest_cached(struct kvm *k
 	struct kvm_memslots *slots = kvm_memslots(kvm);
 	int r;
 
+	BUG_ON(len > ghc->len);
+
 	if (slots->generation != ghc->generation)
-		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
+
+	if (unlikely(!ghc->memslot))
+		return kvm_write_guest(kvm, ghc->gpa, data, len);
 
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
@@ -1522,8 +1544,13 @@ int kvm_read_guest_cached(struct kvm *kv
 	struct kvm_memslots *slots = kvm_memslots(kvm);
 	int r;
 
+	BUG_ON(len > ghc->len);
+
 	if (slots->generation != ghc->generation)
-		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
+
+	if (unlikely(!ghc->memslot))
+		return kvm_read_guest(kvm, ghc->gpa, data, len);
 
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
