Merge "arm/dt: msm8226: Correct the corner voltage"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 31600ca..23498e5 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -56,15 +56,15 @@
 
 Optional child nodes
 - qcom,<vdd restriction child node name>: Define the name of the child node.
-			If this property exisits, qcom,vdd-rstr-reg, qcom,levels,
-			qcom,min-level and qcom,freq-req need to exist, otherwise
-			we return an error.
+			If this property exisits, qcom,vdd-rstr-reg, qcom,levels
+			need to exist. qcom,min-level is optional if qcom,freq-req
+			exists, otherwise it's required.
 - qcom,vdd-rstr-reg: Name of the rail
 - qcom,levels: Array of the level values. Unit is corner voltage for voltage request
 			or kHz for frequency request.
 - qcom,min-level: Request this level as minimum level when disabling voltage
-			restriction. Unit is corner voltage for voltage request
-			or kHz for frequency request.
+			restriction. Unit is corner voltage for voltage request.
+			This will not be required if qcom,freq-req exists.
 - qcom,freq-req: Flag to determine if we should restrict frequency on this rail
 			instead of voltage.
 
@@ -92,5 +92,11 @@
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
+
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,levels = <1881600 1958400 2265600>;
+			qcom,freq-req;
+		};
 	};
 
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
index 199862f..85ccc5d 100644
--- a/Documentation/devicetree/bindings/pil/pil-pronto.txt
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -14,6 +14,7 @@
 - vdd_pronto_pll-supply: regulator to supply pronto pll.
 - qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
 - qcom,gpio-err-fatal: GPIO used by the wcnss to indicate error fatal to the Apps.
+- qcom,gpio-err-ready: GPIO used by the wcnss to indicate error ready to the Apps.
 - qcom,gpio-proxy-unvote: GPIO used by the wcnss to trigger proxy unvoting in
   the Apps
 - qcom,gpio-force-stop: GPIO used by the Apps to force the wcnss to shutdown.
@@ -32,6 +33,7 @@
 
 		/* GPIO input from wcnss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
 		qcom,proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
 
 		/* GPIO output to wcnss */
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
new file mode 100644
index 0000000..c56f06a
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -0,0 +1,609 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "dsi-panel-sharp-qhd-video.dtsi"
+/include/ "msm8974-leds.dtsi"
+
+/ {
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi_sharp_qhd_video {
+		status = "ok";
+	};
+
+	qcom,hdmi_tx@fd922100 {
+		status = "ok";
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		general {
+			label = "general";
+			gpios = <&pm8941_gpios 23 0x1>;
+			linux,input-type = <1>;
+			linux,code = <102>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	bt_ar3002 {
+		compatible = "qca,ar3002";
+		qca,bt-reset-gpio = <&pm8941_gpios 34 0>;
+	};
+
+	hsic_hub {
+		compatible = "qcom,hsic-smsc-hub";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		smsc,reset-gpio = <&pm8941_gpios 8 0x00>;
+
+		hsic_host: hsic@f9a00000 {
+			compatible = "qcom,hsic-host";
+			reg = <0xf9a00000 0x400>;
+			#address-cells = <0>;
+			interrupt-parent = <&hsic_host>;
+			interrupts = <0 1 2>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0xffffffff>;
+			interrupt-map = <0 &intc 0 136 0
+				1 &intc 0 148 0
+				2 &msmgpio 144 0x8>;
+			interrupt-names = "core_irq", "async_irq", "wakeup";
+			HSIC_VDDCX-supply = <&pm8841_s2>;
+			HSIC_GDSC-supply = <&gdsc_usb_hsic>;
+			hsic,strobe-gpio = <&msmgpio 144 0x00>;
+			hsic,data-gpio = <&msmgpio 145 0x00>;
+			hsic,ignore-cal-pad-config;
+			hsic,strobe-pad-offset = <0x2050>;
+			hsic,data-pad-offset = <0x2054>;
+
+			qcom,msm-bus,name = "hsic";
+			qcom,msm-bus,num-cases = <2>;
+			qcom,msm-bus,active-only = <0>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,vectors-KBps =
+					<85 512 0 0>,
+					<85 512 40000 160000>;
+		};
+	};
+
+	i2c@f9923000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_s3>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 566 1067>;
+			atmel,display-coords = <0 0 540 960>;
+			atmel,i2c-pull-up;
+			atmel,cfg_1 {
+				atmel,family-id = <0x81>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 38, Instance = 0 */
+					0F 02 00 17 04 0C 00 00
+					/* Object 7, Instance = 0 */
+					30 FF 19
+					/* Object 8, Instance = 0 */
+					1B 00 05 01 00 00 08 08 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 13 0B 00 10 23 01 03
+					0A 0F 01 0B 04 05 28 0A 2B 04
+					36 02 00 00 00 00 8F 28 8F 50
+					12 0F 32 32 02
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 03 10 30 00 00 01 00 00
+					/* Object 47, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 48, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00
+					];
+			};
+		};
+	};
+
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "atmel_mxt_ts";
+		qcom,disp-maxx = <540>;
+		qcom,disp-maxy = <960>;
+		qcom,panel-maxx = <566>;
+		qcom,panel-maxy = <1067>;
+		qcom,key-codes = <158 139 102 217>;
+	};
+
+	sound {
+		qcom,model = "apq8074-taiko-db-snd-card";
+		qcom,hdmi-audio-rx;
+
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Analog Mic4",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic",
+			"AMIC5", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Analog Mic6",
+			"AMIC6", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Analog Mic7",
+			"DMIC1", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic1",
+			"DMIC2", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic2",
+			"DMIC3", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic3",
+			"DMIC4", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic4",
+			"DMIC5", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic5",
+			"DMIC6", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic6";
+	};
+};
+
+&mdss_fb0 {
+	qcom,memory-reservation-size = <0x1000000>; /* size 16MB */
+};
+
+&sdcc3 {
+	qcom,sup-voltages = <2000 2000>;
+	status = "ok";
+};
+
+&pm8941_l19 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	qcom,init-voltage = <3300000>;
+	regulator-always-on;
+};
+
+&pm8941_l10 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	qcom,init-voltage = <1800000>;
+	regulator-always-on;
+};
+
+&uart7 {
+	status = "ok";
+	qcom,tx-gpio = <&msmgpio 41 0x00>;
+	qcom,rx-gpio = <&msmgpio 42 0x00>;
+	qcom,cts-gpio = <&msmgpio 43 0x00>;
+	qcom,rfr-gpio = <&msmgpio 44 0x00>;
+};
+
+&usb3 {
+	qcom,charging-disabled;
+};
+
+&slim_msm {
+	taiko_codec {
+		qcom,cdc-micbias2-ext-cap;
+		qcom,cdc-micbias3-ext-cap;
+	};
+};
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,src-sel = <0>;
+	};
+
+	gpio@c100 { /* GPIO 2 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,src-sel = <0>;
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,src-sel = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+		/* TUSB3_HUB-RESET */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <0>;		/* QPNP_PIN_PULL_30 */
+		qcom,vin-sel = <0>;		/* QPNP_PIN_VIN0 VPH */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,invert = <1>;		/* Keep it out of reset */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+		/* HSIC_HUB-RESET */
+		qcom,mode = <1>;		/* DIG_OUT */
+		qcom,pull = <5>;		/* PULL_NO */
+		qcom,out-strength = <2>;	/* STRENGTH_MED */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c800 { /* GPIO 9 */
+		/* GbE_RST_N */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <0>;		/* QPNP_PIN_PULL_30 */
+		qcom,vin-sel = <0>;		/* QPNP_PIN_VIN0 VPH */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,invert = <1>;		/* Keep it out of reset */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c900 { /* GPIO 10 */
+		/* SATA_RST_N */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <0>;		/* QPNP_PIN_PULL_30 */
+		qcom,vin-sel = <0>;		/* QPNP_PIN_VIN0 VPH */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,invert = <1>;		/* Keep it out of reset */
+		qcom,master-en = <1>;
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-sel = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,invert = <1>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@e100 { /* GPIO 34 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,invert = <0>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+		qcom,mode = <1>;  /* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>; /* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */
+		qcom,master-en = <1>;
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+	};
+
+	mpp@a500 { /* MPP 6 */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3*/
+	};
+
+	mpp@a300 { /* MPP 4*/
+	};
+};
+
+&spi_epm {
+	epm-adc@0 {
+		compatible = "cy,epm-adc-cy8c5568lti-114";
+		reg = <0>;
+		interrupt-parent = <&msmgpio>;
+		spi-max-frequency = <960000>;
+		qcom,channels = <31>;
+		qcom,gain = <50 50 50 50 50 100 50 50 50 50
+				50 50 50 50 100 50 50 50 50 100
+				50 50 50 100 50 50 50 1 1 1
+				1>;
+		qcom,rsense = <40 10 10 25 10 1000 75 25 10 25
+				33 500 200 10 500 100 33 200 25 100
+				75 500 50 200 5 5 3 1 1 1
+				1>;
+		qcom,channel-type = <0xf0000000>;
+	};
+};
+
+&spmi_bus {
+	qcom,pm8941@1 {
+		qcom,leds@d000 {
+			qcom,rgb_2 {
+				status = "ok";
+				qcom,default-state = "on";
+				qcom,turn-off-delay-ms = <1000>;
+			};
+		};
+
+		qcom,leds@d800 {
+			status = "okay";
+			qcom,wled_0 {
+				label = "wled";
+				linux,name = "wled:backlight";
+				linux,default-trigger = "bkl-trigger";
+				qcom,cs-out-en;
+				qcom,op-fdbck = <1>;
+				qcom,default-state = "on";
+				qcom,max-current = <25>;
+				qcom,ctrl-delay-us = <0>;
+				qcom,boost-curr-lim = <3>;
+				qcom,cp-sel = <0>;
+				qcom,switch-freq = <2>;
+				qcom,ovp-val = <2>;
+				qcom,num-strings = <1>;
+				qcom,id = <0>;
+			};
+		};
+	};
+};
+
+&pm8941_chg {
+	status = "ok";
+
+	qcom,chg-charging-disabled;
+
+	qcom,chg-chgr@1000 {
+		status = "ok";
+	};
+
+	qcom,chg-buck@1100 {
+		status = "ok";
+	};
+
+	qcom,chg-usb-chgpth@1300 {
+		status = "ok";
+	};
+
+	qcom,chg-dc-chgpth@1400 {
+		status = "ok";
+	};
+
+	qcom,chg-boost@1500 {
+		status = "ok";
+	};
+
+	qcom,chg-misc@1600 {
+		status = "ok";
+	};
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm8941_l20>;
+	vdd-io-supply = <&pm8941_s3>;
+
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <800 500000>;
+
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <250 154000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,nonremovable;
+	status = "ok";
+};
+
+&sdhc_2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+
+	vdd-supply = <&pm8941_l21>;
+	vdd-io-supply = <&pm8941_l13>;
+
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <9000 800000>;
+
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <6 22000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/apq8074-v2-dragonboard.dts b/arch/arm/boot/dts/apq8074-v2-dragonboard.dts
new file mode 100644
index 0000000..5a6f5f3
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v2-dragonboard.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "apq8074-v2.dtsi"
+/include/ "apq8074-dragonboard.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8074v2 DRAGONBOARD";
+	compatible = "qcom,apq8074-dragonboard", "qcom,apq8074", "qcom,dragonboard";
+	qcom,msm-id = <184 10 0x20000>;
+};
diff --git a/arch/arm/boot/dts/apq8074-v2.dtsi b/arch/arm/boot/dts/apq8074-v2.dtsi
index 3b65236..9c93ed4 100644
--- a/arch/arm/boot/dts/apq8074-v2.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.dtsi
@@ -18,7 +18,7 @@
 
 /include/ "msm8974-v2.dtsi"
 
-/ {
+&soc {
 	qcom,qseecom@a700000 {
 		compatible = "qcom,qseecom";
 		reg = <0x0a700000 0x500000>;
diff --git a/arch/arm/boot/dts/apq8084-ion.dtsi b/arch/arm/boot/dts/apq8084-ion.dtsi
index aac4230..ea954b8 100644
--- a/arch/arm/boot/dts/apq8084-ion.dtsi
+++ b/arch/arm/boot/dts/apq8084-ion.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,ion {
 		compatible = "qcom,msm-ion";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/apq8084-sim.dts b/arch/arm/boot/dts/apq8084-sim.dts
index ebcca1b..e206d4d 100644
--- a/arch/arm/boot/dts/apq8084-sim.dts
+++ b/arch/arm/boot/dts/apq8084-sim.dts
@@ -22,7 +22,9 @@
 	aliases {
 		serial0 = &uart0;
 	};
+};
 
+&soc {
 	uart0: serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 95b1c8f..ba1ccd7 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -11,12 +11,20 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "apq8084-ion.dtsi"
 
 / {
 	model = "Qualcomm APQ 8084";
 	compatible = "qcom,apq8084";
 	interrupt-parent = <&intc>;
+	soc: soc { };
+};
+
+/include/ "apq8084-ion.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
 
 	intc: interrupt-controller@f9000000 {
 		compatible = "qcom,msm-qgic2";
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index c0c9107..10ca8a8 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,mdss_dsi_nt35590_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
 		label = "nt35590 720p video mode dsi panel";
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
index 448d357..a27a88a 100644
--- a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,mdss_dsi_orise_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
 		label = "orise 720p video mode dsi panel";
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
index f853285..d182bac 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,mdss_dsi_sharp_qhd_video {
 		compatible = "qcom,mdss-dsi-panel";
 		label = "sharp QHD LS043T1LE01 video mode dsi panel";
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index 9a734a0..3b39dea 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 
 	qcom,mdss_dsi_sim_video {
 		compatible = "qcom,mdss-dsi-panel";
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index 2937cde..82b57cd 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 
 	qcom,mdss_dsi_toshiba_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
diff --git a/arch/arm/boot/dts/mpq8092-ion.dtsi b/arch/arm/boot/dts/mpq8092-ion.dtsi
index 2cd2f7b..ee3fbc4 100644
--- a/arch/arm/boot/dts/mpq8092-ion.dtsi
+++ b/arch/arm/boot/dts/mpq8092-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,ion {
 		compatible = "qcom,msm-ion";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/mpq8092-sim.dts b/arch/arm/boot/dts/mpq8092-sim.dts
index fc07c59..ce97d4d 100644
--- a/arch/arm/boot/dts/mpq8092-sim.dts
+++ b/arch/arm/boot/dts/mpq8092-sim.dts
@@ -18,7 +18,9 @@
 	model = "Qualcomm MPQ8092 Simulator";
 	compatible = "qcom,mpq8092-sim", "qcom,mpq8092";
 	qcom,msm-id = <126 16 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index c92dad9..4dea9e0 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -11,15 +11,24 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "mpq8092-iommu.dtsi"
-/include/ "msm-gdsc.dtsi"
-/include/ "mpq8092-ion.dtsi"
 
 / {
 	model = "Qualcomm MPQ8092";
 	compatible = "qcom,mpq8092";
 	interrupt-parent = <&intc>;
 
+	soc: soc { };
+};
+
+/include/ "mpq8092-iommu.dtsi"
+/include/ "msm-gdsc.dtsi"
+/include/ "mpq8092-ion.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
 	intc: interrupt-controller@f9000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
diff --git a/arch/arm/boot/dts/msm-gdsc.dtsi b/arch/arm/boot/dts/msm-gdsc.dtsi
index cfd68fa..d4c5061 100644
--- a/arch/arm/boot/dts/msm-gdsc.dtsi
+++ b/arch/arm/boot/dts/msm-gdsc.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	gdsc_venus: qcom,gdsc@fd8c1024 {
 		compatible = "qcom,gdsc";
 		regulator-name = "gdsc_venus";
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
index 0c44fb5..1cc3c59 100644
--- a/arch/arm/boot/dts/msm-iommu-v0.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	lpass_iommu: qcom,iommu@fd000000 {
 		compatible = "qcom,msm-smmu-v0";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm-iommu-v1.dtsi b/arch/arm/boot/dts/msm-iommu-v1.dtsi
index 71dcc6a..f495850 100644
--- a/arch/arm/boot/dts/msm-iommu-v1.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v1.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	jpeg_iommu: qcom,iommu@fda64000 {
 		compatible = "qcom,msm-smmu-v1";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-bus.dtsi b/arch/arm/boot/dts/msm8226-bus.dtsi
index 3c41e9e..d87aa3e 100644
--- a/arch/arm/boot/dts/msm8226-bus.dtsi
+++ b/arch/arm/boot/dts/msm8226-bus.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	msm-mmss-noc@fc478000 {
 		compatible = "msm-bus-fabric";
 		reg = <0xfc478000 0x00004000>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index c47d48d..07f16b9 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -11,7 +11,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 
 	led_flash0: qcom,camera-led-flash {
 		cell-index = <0>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index 1f7ba89..f06033e 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -11,7 +11,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 
 	led_flash0: qcom,camera-led-flash {
 		cell-index = <0>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index 5ea02b4..47f4049 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -11,7 +11,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 
 	led_flash0: qcom,camera-led-flash {
 		cell-index = <0>;
diff --git a/arch/arm/boot/dts/msm8226-camera.dtsi b/arch/arm/boot/dts/msm8226-camera.dtsi
index e94459e..0dae162 100644
--- a/arch/arm/boot/dts/msm8226-camera.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera.dtsi
@@ -11,7 +11,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,msm-cam@fd8c0000 {
 		compatible = "qcom,msm-cam";
 		reg = <0xfd8c0000 0x10000>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index b203540..f887740 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -19,7 +19,9 @@
 	model = "Qualcomm MSM 8226 CDP";
 	compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
 	qcom,msm-id = <145 1 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 993b4e6..e4a42fa 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	tmc_etr: tmc@fc322000 {
 		compatible = "arm,coresight-tmc";
 		reg = <0xfc322000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index d70ef6e..7b11200 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -17,7 +17,9 @@
 	model = "Qualcomm MSM 8226 FLUID";
 	compatible = "qcom,msm8226-fluid", "qcom,msm8226", "qcom,fluid";
 	qcom,msm-id = <145 3 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "disabled";
 	};
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index bb2f0d4..d83df1e 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	msm_gpu: qcom,kgsl-3d0@fdb00000 {
 		label = "kgsl-3d0";
 		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
@@ -22,8 +22,7 @@
 
 		qcom,chipid = <0x03000510>;
 
-		qcom,initial-pwrlevel = <2>;
-		qcom,step-pwrlevel = <2>;
+		qcom,initial-pwrlevel = <1>;
 
 		qcom,idle-timeout = <8>; //<HZ/12>
 		qcom,nap-allowed = <1>;
diff --git a/arch/arm/boot/dts/msm8226-iommu-domains.dtsi b/arch/arm/boot/dts/msm8226-iommu-domains.dtsi
index 6ea5b9e..25fca2a 100644
--- a/arch/arm/boot/dts/msm8226-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8226-iommu-domains.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,iommu-domains {
 		compatible = "qcom,iommu-domains";
 
diff --git a/arch/arm/boot/dts/msm8226-ion.dtsi b/arch/arm/boot/dts/msm8226-ion.dtsi
index 9ada271..dee64e5 100644
--- a/arch/arm/boot/dts/msm8226-ion.dtsi
+++ b/arch/arm/boot/dts/msm8226-ion.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,ion {
 		compatible = "qcom,msm-ion";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 5aa39d3..f580897 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp";
 		reg = <0xfd900000 0x22100>,
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 1f8a773..3dd517b 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -19,7 +19,9 @@
 	model = "Qualcomm MSM 8226 MTP";
 	compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
 	qcom,msm-id = <145 8 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 7986d81..3240efb 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -12,7 +12,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	qcom,spm@f9089000 {
 		compatible = "qcom,spm-v2";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 660fb3e..721bcbb 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -19,7 +19,9 @@
 	model = "Qualcomm MSM 8226 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
 	qcom,msm-id = <145 11 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 4551f03..7fa9081 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -26,7 +26,7 @@
 
 /* CPR controlled regulator */
 
-/ {
+&soc {
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
 		compatible = "qcom,cpr-regulator";
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 00c0e2e..3cca8b0 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -18,7 +18,9 @@
 	model = "Qualcomm MSM 8226 Simulator";
 	compatible = "qcom,msm8226-sim", "qcom,msm8226", "qcom,sim";
 	qcom,msm-id = <145 16 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8226-smp2p.dtsi b/arch/arm/boot/dts/msm8226-smp2p.dtsi
index 079e4ca..3921a68 100644
--- a/arch/arm/boot/dts/msm8226-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8226-smp2p.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	qcom,smp2p-modem {
 		compatible = "qcom,smp2p";
 		reg = <0xf9011008 0x4>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index f71e916..6c06336 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -11,42 +11,12 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "msm8226-ion.dtsi"
-/include/ "msm8226-camera.dtsi"
-/include/ "msm-gdsc.dtsi"
-/include/ "msm8226-iommu.dtsi"
-/include/ "msm8226-pm.dtsi"
-/include/ "msm8226-smp2p.dtsi"
-/include/ "msm8226-gpu.dtsi"
-/include/ "msm8226-bus.dtsi"
-/include/ "msm8226-mdss.dtsi"
-/include/ "msm8226-coresight.dtsi"
-/include/ "msm8226-iommu-domains.dtsi"
+
 / {
 	model = "Qualcomm MSM 8226";
 	compatible = "qcom,msm8226";
 	interrupt-parent = <&intc>;
 
-	intc: interrupt-controller@f9000000 {
-		compatible = "qcom,msm-qgic2";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		reg = <0xF9000000 0x1000>,
-		      <0xF9002000 0x1000>;
-	};
-
-	msmgpio: gpio@fd510000 {
-		compatible = "qcom,msm-gpio";
-		interrupt-controller;
-		#interrupt-cells = <2>;
-		reg = <0xfd510000 0x4000>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpio = <117>;
-		interrupts = <0 208 0>;
-		qcom,direct-connect-irqs = <8>;
-	};
-
 	aliases {
 		spi0 = &spi_0;
 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
@@ -65,7 +35,46 @@
 			reg = <0 0x780000>;
 			label = "qsecom_mem";
 		};
+	};
 
+	soc: soc { };
+};
+
+/include/ "msm8226-ion.dtsi"
+/include/ "msm8226-camera.dtsi"
+/include/ "msm-gdsc.dtsi"
+/include/ "msm8226-iommu.dtsi"
+/include/ "msm8226-pm.dtsi"
+/include/ "msm8226-smp2p.dtsi"
+/include/ "msm8226-gpu.dtsi"
+/include/ "msm8226-bus.dtsi"
+/include/ "msm8226-mdss.dtsi"
+/include/ "msm8226-coresight.dtsi"
+/include/ "msm8226-iommu-domains.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xF9000000 0x1000>,
+		      <0xF9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpio = <117>;
+		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 	qcom,mpm2-sleep-counter@fc4a3000 {
@@ -750,6 +759,7 @@
 
 		/* GPIO inputs from wcnss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
 
 		/* GPIO output to wcnss */
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index 50066f3..2e7ba25 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	msm-mmss-noc@fc478000 {
 		compatible = "msm-bus-fabric";
 		reg = <0xfc478000 0x00004000>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6161ad2..28e9dc5 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -20,7 +20,9 @@
 	compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
 	qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
 		      <163 1 0>, <164 1 0>, <166 1 0>;
+};
 
+&soc {
 	serial@f991e000 {
 		status = "ok";
 	};
@@ -88,6 +90,51 @@
 	};
 };
 
+&i2c_cdc  {
+	msm8x10_wcd_codec@0d{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x0d>;
+		cdc-vdda-cp-supply = <&pm8110_s4>;
+		qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+		qcom,cdc-vdda-cp-current = <650000>;
+
+		cdc-vdda-h-supply = <&pm8110_l6>;
+		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdda-h-current = <250000>;
+
+		cdc-vdd-px-supply = <&pm8110_l6>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-1p2v-supply = <&pm8110_l4>;
+		qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+		qcom,cdc-vdd-1p2v-current = <5000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <25000>;
+
+		qcom,cdc-micbias-cfilt-sel = <0x0>;
+		qcom,cdc-micbias-cfilt-mv = <1800000>;
+		qcom,cdc-mclk-clk-rate = <12288000>;
+	};
+
+	msm8x10_wcd_codec@77{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x77>;
+	};
+
+	msm8x10_wcd_codec@66{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x66>;
+	};
+
+	msm8x10_wcd_codec@55{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x55>;
+	};
+};
+
 &spmi_bus {
 	qcom,pm8110@0 {
 		qcom,leds@a100 {
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index a0a2c14..4945693 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	tmc_etr: tmc@fc326000 {
 		compatible = "arm,coresight-tmc";
 		reg = <0xfc326000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8610-gpu.dtsi b/arch/arm/boot/dts/msm8610-gpu.dtsi
index 5580f73..d1b30ee 100644
--- a/arch/arm/boot/dts/msm8610-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8610-gpu.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	msm_gpu: qcom,kgsl-3d0@fdc00000 {
 		label = "kgsl-3d0";
 		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
diff --git a/arch/arm/boot/dts/msm8610-iommu-domains.dtsi b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
index 0f48517..6f43897 100644
--- a/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,iommu-domains {
 		compatible = "qcom,iommu-domains";
 
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 7d7d8fd..456b60c 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,ion {
 		compatible = "qcom,msm-ion";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index 42fa149..1766422 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp3";
 		reg = <0xfd900000 0x100000>;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index eabeca6..83e7b48 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -20,7 +20,9 @@
 	compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
 	qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
 		      <163 8 0>, <164 8 0>, <166 8 0>;
+};
 
+&soc {
 	serial@f991e000 {
 		status = "ok";
 	};
@@ -88,6 +90,51 @@
 	};
 };
 
+&i2c_cdc  {
+	msm8x10_wcd_codec@0d{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x0d>;
+		cdc-vdda-cp-supply = <&pm8110_s4>;
+		qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+		qcom,cdc-vdda-cp-current = <650000>;
+
+		cdc-vdda-h-supply = <&pm8110_l6>;
+		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdda-h-current = <250000>;
+
+		cdc-vdd-px-supply = <&pm8110_l6>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-1p2v-supply = <&pm8110_l4>;
+		qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+		qcom,cdc-vdd-1p2v-current = <5000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <25000>;
+
+		qcom,cdc-micbias-cfilt-sel = <0x0>;
+		qcom,cdc-micbias-cfilt-mv = <1800000>;
+		qcom,cdc-mclk-clk-rate = <12288000>;
+	};
+
+	msm8x10_wcd_codec@77{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x77>;
+	};
+
+	msm8x10_wcd_codec@66{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x66>;
+	};
+
+	msm8x10_wcd_codec@55{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x55>;
+	};
+};
+
 &spmi_bus {
 	qcom,pm8110@0 {
 		qcom,leds@a100 {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index baae269..34382c5 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -12,7 +12,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	qcom,spm@f9089000 {
 		compatible = "qcom,spm-v2";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index f5d01e0..9e79df1 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -26,7 +26,7 @@
 
 /* CPR controlled regulator */
 
-/ {
+&soc {
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
 		compatible = "qcom,cpr-regulator";
diff --git a/arch/arm/boot/dts/msm8610-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
index cab7560..7f06485 100644
--- a/arch/arm/boot/dts/msm8610-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -18,7 +18,9 @@
 	model = "Qualcomm MSM 8610 Rumi";
 	compatible = "qcom,msm8610-rumi", "qcom,msm8610", "qcom,rumi";
 	qcom,msm-id = <147 15 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8610-sim.dts b/arch/arm/boot/dts/msm8610-sim.dts
index 1838b94..7c57fe6 100644
--- a/arch/arm/boot/dts/msm8610-sim.dts
+++ b/arch/arm/boot/dts/msm8610-sim.dts
@@ -18,8 +18,55 @@
 	model = "Qualcomm MSM 8610 Simulator";
 	compatible = "qcom,msm8610-sim", "qcom,msm8610", "qcom,sim";
 	qcom,msm-id = <147 16 0>;
+};
 
+&soc {
 	serial@f991f000 {
 		status = "ok";
 	};
 };
+
+&i2c_cdc  {
+	msm8x10_wcd_codec@0d{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x0d>;
+		cdc-vdda-cp-supply = <&pm8110_s4>;
+		qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+		qcom,cdc-vdda-cp-current = <650000>;
+
+		cdc-vdda-h-supply = <&pm8110_l6>;
+		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdda-h-current = <250000>;
+
+		cdc-vdd-px-supply = <&pm8110_l6>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-1p2v-supply = <&pm8110_l4>;
+		qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+		qcom,cdc-vdd-1p2v-current = <5000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <25000>;
+
+		qcom,cdc-micbias-cfilt-sel = <0x0>;
+		qcom,cdc-micbias-cfilt-mv = <1800000>;
+		qcom,cdc-mclk-clk-rate = <12288000>;
+	};
+
+	msm8x10_wcd_codec@77{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x77>;
+	};
+
+	msm8x10_wcd_codec@66{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x66>;
+	};
+
+	msm8x10_wcd_codec@55{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x55>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610-smp2p.dtsi b/arch/arm/boot/dts/msm8610-smp2p.dtsi
index 079e4ca..3921a68 100644
--- a/arch/arm/boot/dts/msm8610-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8610-smp2p.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	qcom,smp2p-modem {
 		compatible = "qcom,smp2p";
 		reg = <0xf9011008 0x4>;
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 1c2da1c..4b861ed 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -11,6 +11,28 @@
  */
 
 /include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610";
+	compatible = "qcom,msm8610";
+	interrupt-parent = <&intc>;
+
+	memory {
+		qsecom_mem: qsecom_region {
+			linux,contiguous-region;
+			reg = <0 0x100000>;
+			label = "qsecom_mem";
+		};
+	};
+
+	aliases {
+		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+	};
+
+	soc: soc { };
+};
+
 /include/ "msm-iommu-v0.dtsi"
 /include/ "msm8610-ion.dtsi"
 /include/ "msm8610-gpu.dtsi"
@@ -21,10 +43,10 @@
 /include/ "msm8610-bus.dtsi"
 /include/ "msm8610-mdss.dtsi"
 
-/ {
-	model = "Qualcomm MSM 8610";
-	compatible = "qcom,msm8610";
-	interrupt-parent = <&intc>;
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
 
 	intc: interrupt-controller@f9000000 {
 		compatible = "qcom,msm-qgic2";
@@ -46,21 +68,6 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
-	memory {
-
-		qsecom_mem: qsecom_region {
-			linux,contiguous-region;
-			reg = <0 0x100000>;
-			label = "qsecom_mem";
-		};
-
-	};
-
-	aliases {
-		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
-		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
-	};
-
 	qcom,mpm2-sleep-counter@fc4a3000 {
 		compatible = "qcom,mpm2-sleep-counter";
 		reg = <0xfc4a3000 0x1000>;
@@ -448,6 +455,18 @@
 		qcom,scl-gpio = <&msmgpio 3 0>;
 	};
 
+	i2c_cdc: i2c@f9927000 { /* BLSP1 QUP5 */
+                cell-index = <5>;
+                compatible = "qcom,i2c-qup";
+                #address-cells = <1>;
+                #size-cells = <0>;
+                reg-names = "qup_phys_addr";
+                reg = <0xf9927000 0x1000>;
+                interrupt-names = "qup_err_intr";
+                interrupts = <0 99 0>;
+                qcom,i2c-bus-freq = <100000>;
+        };
+
 	i2c@f9928000 { /* BLSP1 QUP6 */
 		cell-index = <6>;
 		compatible = "qcom,i2c-qup";
@@ -488,6 +507,7 @@
 
 		/* GPIO inputs from wcnss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
 
 		/* GPIO output to wcnss */
@@ -751,6 +771,12 @@
                 qcom,msm-rng-iface-clk;
         };
 
+	qcom,msm-rtb {
+		compatible = "qcom,msm-rtb";
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+	};
+
 	jtag_mm0: jtagmm@fc34c000 {
 		compatible = "qcom,jtag-mm";
 		reg = <0xfc34c000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index 3e0ef04..bfe955e 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	msm-mmss-noc@fc478000 {
 		compatible = "msm-bus-fabric";
 		reg = <0xfc478000 0x00004000>;
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 94a28f7..786e9e3 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -13,7 +13,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	qcom,msm-cam@fd8C0000 {
 		compatible = "qcom,msm-cam";
 		reg = <0xfd8C0000 0x10000>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 9cfc5fd..72b6223 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -15,7 +15,7 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-cdp.dtsi"
 
-/ {
+&soc {
 	serial@f991e000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index c064b59..cccedd8 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	tmc_etr: tmc@fc322000 {
 		compatible = "arm,coresight-tmc";
 		reg = <0xfc322000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 7f46a54..06b13b8 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -14,7 +14,7 @@
 /include/ "msm8974-camera-sensor-fluid.dtsi"
 /include/ "msm8974-leds.dtsi"
 
-/ {
+&soc {
 	serial@f991e000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 3779dbd..669097e 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	msm_gpu: qcom,kgsl-3d0@fdb00000 {
 		label = "kgsl-3d0";
 		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index cfe39fc..ee8152d 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,ion {
 		compatible = "qcom,msm-ion";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index d8a090b..3f4e035 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -13,7 +13,7 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-liquid.dtsi"
 
-/ {
+&soc {
 	serial@f991e000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 86f8141..6b8d600 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	mdss_mdp: qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp";
 		reg = <0xfd900000 0x22100>,
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index ca5f663..37286af 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -14,7 +14,7 @@
 /include/ "msm8974-camera-sensor-mtp.dtsi"
 /include/ "msm8974-leds.dtsi"
 
-/ {
+&soc {
 	serial@f991e000 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index d1b3334..2cd3d24 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -458,7 +458,7 @@
 	};
 };
 
-/ {
+&soc {
 	krait_pdn: krait-pdn@f9011000 {
 		reg = <0xf9011000 0x1000>;
 		reg-names = "apcs_gcc";
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
index c569e58..c01a4e5 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dtsi
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -13,7 +13,7 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-cdp.dtsi"
 
-/ {
+&soc {
 	timer {
 		clock-frequency = <5000000>;
 	};
diff --git a/arch/arm/boot/dts/msm8974-sim.dtsi b/arch/arm/boot/dts/msm8974-sim.dtsi
index 786c50c..24b8d18 100644
--- a/arch/arm/boot/dts/msm8974-sim.dtsi
+++ b/arch/arm/boot/dts/msm8974-sim.dtsi
@@ -14,7 +14,7 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-cdp.dtsi"
 
-/ {
+&soc {
 	qcom,mdss_dsi@fd922800 {
 		qcom,mdss_dsi_sim_video {
 			status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-smp2p.dtsi b/arch/arm/boot/dts/msm8974-smp2p.dtsi
index 079e4ca..3921a68 100644
--- a/arch/arm/boot/dts/msm8974-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8974-smp2p.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	qcom,smp2p-modem {
 		compatible = "qcom,smp2p";
 		reg = <0xf9011008 0x4>;
diff --git a/arch/arm/boot/dts/msm8974-v1-iommu-domains.dtsi b/arch/arm/boot/dts/msm8974-v1-iommu-domains.dtsi
index 6ea5b9e..25fca2a 100644
--- a/arch/arm/boot/dts/msm8974-v1-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-iommu-domains.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,iommu-domains {
 		compatible = "qcom,iommu-domains";
 
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index f9c0920..1a88749 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -12,7 +12,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	qcom,spm@f9089000 {
 		compatible = "qcom,spm-v2";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index 62837a1..caec2dc 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -21,7 +21,7 @@
 /include/ "msm8974-v1-iommu-domains.dtsi"
 /include/ "msm8974-v1-pm.dtsi"
 
-/ {
+&soc {
 	android_usb@fc42b0c8 {
 		compatible = "qcom,android-usb";
 		reg = <0xfc42b0c8 0xc8>;
diff --git a/arch/arm/boot/dts/msm8974-v2-iommu-domains.dtsi b/arch/arm/boot/dts/msm8974-v2-iommu-domains.dtsi
index a83815e..01c94d0 100644
--- a/arch/arm/boot/dts/msm8974-v2-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-iommu-domains.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,iommu-domains {
 		compatible = "qcom,iommu-domains";
 
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 5a1c047..f8492c0 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -12,7 +12,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	qcom,spm@f9089000 {
 		compatible = "qcom,spm-v2";
 	#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index def7b8c..75dce17 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -21,7 +21,7 @@
 /include/ "msm8974-v2-iommu-domains.dtsi"
 /include/ "msm8974-v2-pm.dtsi"
 
-/ {
+&soc {
 	android_usb@fe8050c8 {
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 5f010a3..71bbdc5 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -11,14 +11,6 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "msm8974-camera.dtsi"
-/include/ "msm8974-coresight.dtsi"
-/include/ "msm-gdsc.dtsi"
-/include/ "msm8974-ion.dtsi"
-/include/ "msm8974-gpu.dtsi"
-/include/ "msm8974-mdss.dtsi"
-/include/ "msm8974-smp2p.dtsi"
-/include/ "msm8974-bus.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974";
@@ -35,7 +27,6 @@
 	};
 
 	memory {
-
 		secure_mem: secure_region {
 			linux,contiguous-region;
 			reg = <0 0xFC00000>;
@@ -56,6 +47,23 @@
 
 	};
 
+	soc: soc { };
+};
+
+/include/ "msm8974-camera.dtsi"
+/include/ "msm8974-coresight.dtsi"
+/include/ "msm-gdsc.dtsi"
+/include/ "msm8974-ion.dtsi"
+/include/ "msm8974-gpu.dtsi"
+/include/ "msm8974-mdss.dtsi"
+/include/ "msm8974-smp2p.dtsi"
+/include/ "msm8974-bus.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
 	intc: interrupt-controller@F9000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
@@ -1145,6 +1153,7 @@
 
 		/* GPIO inputs from wcnss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
 
 		/* GPIO output to wcnss */
@@ -1186,7 +1195,7 @@
 		interrupts = <0 76 0 0 77 0>;
 		interrupt-names = "ocmem_irq", "dm_irq";
 		qcom,ocmem-num-regions = <0x3>;
-		qcom,ocmem-num-macros = <0x8>;
+		qcom,ocmem-num-macros = <0x18>;
 		qcom,resource-type = <0x706d636f>;
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1433,6 +1442,11 @@
 			qcom,min-level = <1>; /* No Request */
 		};
 
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,levels = <1881600 1958400 2265600>;
+			qcom,freq-req;
+		};
 	};
 
 	qcom,bam_dmux@fc834000 {
diff --git a/arch/arm/boot/dts/msm9625-cdp.dtsi b/arch/arm/boot/dts/msm9625-cdp.dtsi
index 1f9cbb0..6ddb50b 100644
--- a/arch/arm/boot/dts/msm9625-cdp.dtsi
+++ b/arch/arm/boot/dts/msm9625-cdp.dtsi
@@ -13,7 +13,7 @@
 /include/ "msm9625-display.dtsi"
 /include/ "qpic-panel-ili-qvga.dtsi"
 
-/ {
+&soc {
 	i2c@f9925000 {
 		charger@57 {
 			compatible = "summit,smb137c";
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 69a1d7b..8520b19 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	tmc_etr: tmc@fc322000 {
 		compatible = "arm,coresight-tmc";
 		reg = <0xfc322000 0x1000>,
diff --git a/arch/arm/boot/dts/msm9625-display.dtsi b/arch/arm/boot/dts/msm9625-display.dtsi
index a160bae..287a63a 100644
--- a/arch/arm/boot/dts/msm9625-display.dtsi
+++ b/arch/arm/boot/dts/msm9625-display.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,msm_qpic@f9ac0000 {
 		compatible = "qcom,mdss_qpic";
 		reg = <0xf9ac0000 0x24000>;
diff --git a/arch/arm/boot/dts/msm9625-ion.dtsi b/arch/arm/boot/dts/msm9625-ion.dtsi
index 8183264..2a3e4b5 100644
--- a/arch/arm/boot/dts/msm9625-ion.dtsi
+++ b/arch/arm/boot/dts/msm9625-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,ion {
 		compatible = "qcom,msm-ion";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm9625-mtp.dtsi b/arch/arm/boot/dts/msm9625-mtp.dtsi
index cc0bf5e..79c873f 100644
--- a/arch/arm/boot/dts/msm9625-mtp.dtsi
+++ b/arch/arm/boot/dts/msm9625-mtp.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	i2c@f9925000 {
 		charger@57 {
 			compatible = "summit,smb137c";
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 3e421a8..6c45f80 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -12,7 +12,7 @@
 
 /include/ "skeleton.dtsi"
 
-/ {
+&soc {
 	qcom,spm@f9009000 {
 		compatible = "qcom,spm-v2";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm9625-regulator.dtsi b/arch/arm/boot/dts/msm9625-regulator.dtsi
index 24f616d..ee48b7f 100644
--- a/arch/arm/boot/dts/msm9625-regulator.dtsi
+++ b/arch/arm/boot/dts/msm9625-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -260,7 +260,7 @@
 	};
 };
 
-/ {
+&soc {
 	ext_2p95v: regulator-isl80101 {
 		compatible = "regulator-fixed";
 		regulator-name = "ext_2p95v";
diff --git a/arch/arm/boot/dts/msm9625-smp2p.dtsi b/arch/arm/boot/dts/msm9625-smp2p.dtsi
index 46af1b2..f8ad351 100644
--- a/arch/arm/boot/dts/msm9625-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm9625-smp2p.dtsi
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/ {
+&soc {
 	qcom,smp2p-modem {
 		compatible = "qcom,smp2p";
 		reg = <0xf9011008 0x4>;
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index de88ff1..b238ba5 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -18,7 +18,7 @@
 
 /include/ "msm9625.dtsi"
 
-/ {
+&soc {
 	qcom,msm-imem@fc42a800 {
 		compatible = "qcom,msm-imem";
 		reg = <0xfc42a800 0x1000>; /* Address and size of IMEM */
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index 5324e2c..27d0066 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -21,7 +21,9 @@
 	qcom,msm-id = <134 7 0x20000>, <152 7 0x20000>, <149 7 0x20000>,
 		      <150 7 0x20000>, <151 7 0x20000>, <148 7 0x20000>,
 		      <173 7 0x20000>, <174 7 0x20000>, <175 7 0x20000>;
+};
 
+&soc {
 	i2c@f9925000 {
 		charger@57 {
 			compatible = "summit,smb137c";
diff --git a/arch/arm/boot/dts/msm9625-v2.1.dtsi b/arch/arm/boot/dts/msm9625-v2.1.dtsi
index c3c2c49..65ff96a 100644
--- a/arch/arm/boot/dts/msm9625-v2.1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v2.1.dtsi
@@ -18,7 +18,7 @@
 
 /include/ "msm9625.dtsi"
 
-/ {
+&soc {
 	qcom,msm-imem@fe807800 {
 		compatible = "qcom,msm-imem";
 		reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
diff --git a/arch/arm/boot/dts/msm9625-v2.dtsi b/arch/arm/boot/dts/msm9625-v2.dtsi
index 81d8e00..b078309 100644
--- a/arch/arm/boot/dts/msm9625-v2.dtsi
+++ b/arch/arm/boot/dts/msm9625-v2.dtsi
@@ -18,7 +18,7 @@
 
 /include/ "msm9625.dtsi"
 
-/ {
+&soc {
 	qcom,msm-imem@fe807800 {
 		compatible = "qcom,msm-imem";
 		reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 3e2eab3..f614d61 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -11,10 +11,6 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "msm9625-ion.dtsi"
-/include/ "msm9625-pm.dtsi"
-/include/ "msm9625-coresight.dtsi"
-/include/ "msm9625-smp2p.dtsi"
 
 / {
 	model = "Qualcomm MSM 9625";
@@ -25,6 +21,19 @@
 		spi0 = &spi_0;
 	};
 
+	soc: soc { };
+};
+
+/include/ "msm9625-ion.dtsi"
+/include/ "msm9625-pm.dtsi"
+/include/ "msm9625-coresight.dtsi"
+/include/ "msm9625-smp2p.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
 	intc: interrupt-controller@F9000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 3f51659..4b032d8 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -17,6 +17,14 @@
 	compatible = "qcom,msmkrypton";
 	interrupt-parent = <&intc>;
 
+	soc: soc { };
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
 	intc: interrupt-controller@f9000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
diff --git a/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi b/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi
index a0c906e..089f112 100644
--- a/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi
+++ b/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/ {
+&soc {
 	qcom,mdss_lcdc_ili9341_qvga {
 		compatible = "qcom,mdss-qpic-panel";
 		label = "ili qvga lcdc panel";
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 3729448..0eecffd 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -418,6 +418,7 @@
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
+	select ARM_TICKET_LOCKS
 	select GPIO_MSM_V3
 	select MSM_GPIOMUX
 	select MSM_NATIVE_RESTART
@@ -459,6 +460,7 @@
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
+	select ARM_TICKET_LOCKS
 	select GPIO_MSM_V3
 	select MSM_GPIOMUX
 	select MSM_NATIVE_RESTART
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 43b243d..8efc000 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -4,7 +4,7 @@
 ifndef CONFIG_ARM_ARCH_TIMER
 obj-y += timer.o
 endif
-obj-y += clock.o clock-voter.o clock-dummy.o
+obj-y += clock.o clock-voter.o clock-dummy.o clock-generic.o
 obj-y += modem_notifier.o
 obj-$(CONFIG_USE_OF) += board-dt.o
 obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index d57709d..2827e65 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -58,6 +58,7 @@
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-liquid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-liquid.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-dragonboard.dtb
 
 # APQ8084
    zreladdr-$(CONFIG_ARCH_APQ8084)	:= 0x00008000
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 0a13c56..c20ba92 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -120,7 +120,7 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	apq8084_init_gpiomux();
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	board_dt_populate(adata);
 	apq8084_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index b4c63f9..3da3e2d 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -102,7 +102,7 @@
 
 	mpq8092_init_gpiomux();
 	msm_clock_init(&mpq8092_clock_init_data);
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	board_dt_populate(adata);
 }
 
 static const char *mpq8092_dt_match[] __initconst = {
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index a892e32..521898e 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -129,7 +129,7 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8226_init_gpiomux();
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	board_dt_populate(adata);
 	msm8226_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 2cd7134..962ed65 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -125,7 +125,7 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8610_init_gpiomux();
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	board_dt_populate(adata);
 	msm8610_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index f5b76da..76dbaef 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1171,6 +1171,23 @@
 static void msm_gpiomux_sdc4_install(void) {}
 #endif /* CONFIG_MMC_MSM_SDC4_SUPPORT */
 
+static struct msm_gpiomux_config apq8074_dragonboard_ts_config[] __initdata = {
+	{
+		/* BLSP1 QUP I2C_DATA */
+		.gpio      = 2,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+	{
+		/* BLSP1 QUP I2C_CLK */
+		.gpio      = 3,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+};
+
 void __init msm_8974_init_gpiomux(void)
 {
 	int rc;
@@ -1236,4 +1253,8 @@
 	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_MDM)
 		msm_gpiomux_install(mdm_configs,
 			ARRAY_SIZE(mdm_configs));
+
+	if (of_board_is_dragonboard() && machine_is_apq8074())
+		msm_gpiomux_install(apq8074_dragonboard_ts_config,
+			ARRAY_SIZE(apq8074_dragonboard_ts_config));
 }
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 3eed219..35e46fc 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -163,7 +163,7 @@
 
 	msm_8974_init_gpiomux();
 	regulator_has_full_constraints();
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	board_dt_populate(adata);
 	msm8974_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 3bb00bb..6bb5655 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -247,8 +247,7 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm9625_init_gpiomux();
-	of_platform_populate(NULL, of_default_bus_match_table,
-			msm9625_auxdata_lookup, NULL);
+	board_dt_populate(msm9625_auxdata_lookup);
 	msm9625_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 5d2fdf9..1f77b4c 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -115,3 +115,14 @@
 
 	return 1;
 }
+
+void __init board_dt_populate(struct of_dev_auxdata *adata)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	/* Explicitly parent the /soc devices to the root node to preserve
+	 * the kernel ABI (sysfs structure, etc) until userspace is updated
+	 */
+	of_platform_populate(of_find_node_by_path("/soc"),
+			     of_default_bus_match_table, adata, NULL);
+}
diff --git a/arch/arm/mach-msm/board-dt.h b/arch/arm/mach-msm/board-dt.h
index 03ffa0b..d79e414 100644
--- a/arch/arm/mach-msm/board-dt.h
+++ b/arch/arm/mach-msm/board-dt.h
@@ -10,9 +10,12 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/of_platform.h>
+
 extern struct sys_timer msm_dt_timer;
 void __init msm_dt_init_irq(void);
 void __init msm_dt_init_irq_nompm(void);
 void __init msm_dt_init_irq_l2x0(void);
 int __init msm_scan_dt_map_imem(unsigned long node, const char *uname,
 				int depth, void *data);
+void __init board_dt_populate(struct of_dev_auxdata *adata);
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
index aada3b0..7b7b7cd 100644
--- a/arch/arm/mach-msm/board-krypton.c
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -64,7 +64,7 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msmkrypton_init_gpiomux();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	board_dt_populate(adata);
 	msmkrypton_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 486842f..27bfcac 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -176,7 +176,7 @@
 	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
 
 #define RPM_MISC_CLK_TYPE	0x306b6c63
 #define RPM_BUS_CLK_TYPE	0x316b6c63
@@ -2760,7 +2760,8 @@
 	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2, vdd_sr2_levels);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2,
+				vdd_sr2_levels, NULL);
 
 static struct pll_freq_tbl apcs_pll_freq[] = {
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 64636c1..5e60bd5 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -441,7 +441,7 @@
 	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
 
 #define RPM_MISC_CLK_TYPE	0x306b6c63
 #define RPM_BUS_CLK_TYPE	0x316b6c63
@@ -540,7 +540,8 @@
 	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2, vdd_sr2_levels);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2,
+				vdd_sr2_levels, NULL);
 
 static struct pll_freq_tbl apcs_pll_freq[] = {
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -2017,7 +2018,7 @@
 	},
 };
 
-static struct mux_clk csi0phy_mux_clk = {
+static struct cam_mux_clk csi0phy_cam_mux_clk = {
 	.enable_reg = MMSS_CAMSS_MISC,
 	.enable_mask = BIT(11),
 	.select_reg = MMSS_CAMSS_MISC,
@@ -2029,13 +2030,13 @@
 	},
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.dbg_name = "csi0phy_mux_clk",
-		.ops = &clk_ops_mux,
-		CLK_INIT(csi0phy_mux_clk.c),
+		.dbg_name = "csi0phy_cam_mux_clk",
+		.ops = &clk_ops_cam_mux,
+		CLK_INIT(csi0phy_cam_mux_clk.c),
 	},
 };
 
-static struct mux_clk csi1phy_mux_clk = {
+static struct cam_mux_clk csi1phy_cam_mux_clk = {
 	.enable_reg = MMSS_CAMSS_MISC,
 	.enable_mask = BIT(10),
 	.select_reg = MMSS_CAMSS_MISC,
@@ -2047,13 +2048,13 @@
 	},
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.dbg_name = "csi1phy_mux_clk",
-		.ops = &clk_ops_mux,
-		CLK_INIT(csi1phy_mux_clk.c),
+		.dbg_name = "csi1phy_cam_mux_clk",
+		.ops = &clk_ops_cam_mux,
+		CLK_INIT(csi1phy_cam_mux_clk.c),
 	},
 };
 
-static struct mux_clk csi0pix_mux_clk = {
+static struct cam_mux_clk csi0pix_cam_mux_clk = {
 	.enable_reg = MMSS_CAMSS_MISC,
 	.enable_mask = BIT(7),
 	.select_reg = MMSS_CAMSS_MISC,
@@ -2065,14 +2066,14 @@
 	},
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.dbg_name = "csi0pix_mux_clk",
-		.ops = &clk_ops_mux,
-		CLK_INIT(csi0pix_mux_clk.c),
+		.dbg_name = "csi0pix_cam_mux_clk",
+		.ops = &clk_ops_cam_mux,
+		CLK_INIT(csi0pix_cam_mux_clk.c),
 	},
 };
 
 
-static struct mux_clk rdi2_mux_clk = {
+static struct cam_mux_clk rdi2_cam_mux_clk = {
 	.enable_reg = MMSS_CAMSS_MISC,
 	.enable_mask = BIT(6),
 	.select_reg = MMSS_CAMSS_MISC,
@@ -2084,13 +2085,13 @@
 	},
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.dbg_name = "rdi2_mux_clk",
-		.ops = &clk_ops_mux,
-		CLK_INIT(rdi2_mux_clk.c),
+		.dbg_name = "rdi2_cam_mux_clk",
+		.ops = &clk_ops_cam_mux,
+		CLK_INIT(rdi2_cam_mux_clk.c),
 	},
 };
 
-static struct mux_clk rdi1_mux_clk = {
+static struct cam_mux_clk rdi1_cam_mux_clk = {
 	.enable_reg = MMSS_CAMSS_MISC,
 	.enable_mask = BIT(5),
 	.select_reg = MMSS_CAMSS_MISC,
@@ -2102,13 +2103,13 @@
 	},
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.dbg_name = "rdi1_mux_clk",
-		.ops = &clk_ops_mux,
-		CLK_INIT(rdi1_mux_clk.c),
+		.dbg_name = "rdi1_cam_mux_clk",
+		.ops = &clk_ops_cam_mux,
+		CLK_INIT(rdi1_cam_mux_clk.c),
 	},
 };
 
-static struct mux_clk rdi0_mux_clk = {
+static struct cam_mux_clk rdi0_cam_mux_clk = {
 	.enable_reg = MMSS_CAMSS_MISC,
 	.enable_mask = BIT(4),
 	.select_reg = MMSS_CAMSS_MISC,
@@ -2120,9 +2121,9 @@
 	},
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.dbg_name = "rdi0_mux_clk",
-		.ops = &clk_ops_mux,
-		CLK_INIT(rdi0_mux_clk.c),
+		.dbg_name = "rdi0_cam_mux_clk",
+		.ops = &clk_ops_cam_mux,
+		CLK_INIT(rdi0_cam_mux_clk.c),
 	},
 };
 
@@ -2495,7 +2496,7 @@
 	{            &gcc_ce1_axi_clk.c, GCC_BASE, 0x0139},
 	{            &gcc_ce1_ahb_clk.c, GCC_BASE, 0x013a},
 	{             &gcc_xo_clk_src.c, GCC_BASE, 0x0149},
-	{                   &bimc_clk.c, GCC_BASE, 0x0154},
+	{                   &bimc_clk.c, GCC_BASE, 0x015d},
 	{          &gcc_bimc_smmu_clk.c, GCC_BASE, 0x015e},
 	{       &gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
 
@@ -2539,11 +2540,11 @@
 	{             &q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
 	{                     &q6ss_xo_clk.c, LPASS_BASE, 0x002b},
 
-	{&apc0_m_clk,                    APCS_BASE, 0x10},
-	{&apc1_m_clk,                    APCS_BASE, 0x11},
-	{&apc2_m_clk,                    APCS_BASE, 0x12},
-	{&apc3_m_clk,                    APCS_BASE, 0x13},
-	{&l2_m_clk,                      APCS_BASE, 0x15},
+	{&apc0_m_clk,                    APCS_BASE, 0x00010},
+	{&apc1_m_clk,                    APCS_BASE, 0x00114},
+	{&apc2_m_clk,                    APCS_BASE, 0x00220},
+	{&apc3_m_clk,                    APCS_BASE, 0x00324},
+	{&l2_m_clk,                      APCS_BASE, 0x01000},
 
 	{&dummy_clk, N_BASES, 0x0000},
 };
@@ -2610,6 +2611,8 @@
 		clk->multiplier = 4;
 		clk_sel = 0x16A;
 		regval = measure_mux[i].debug_mux;
+		/* Use a divider value of 4. */
+		regval |= BVAL(31, 30, 0x3);
 		writel_relaxed(regval, APCS_REG_BASE(GLB_CLK_DIAG));
 		break;
 
@@ -2874,6 +2877,7 @@
 	CLK_LOOKUP("core_clk_src",       usb_hs_system_clk_src.c, ""),
 	CLK_LOOKUP("iface_clk",           gcc_blsp1_ahb_clk.c, "f9923000.i2c"),
 	CLK_LOOKUP("iface_clk",           gcc_blsp1_ahb_clk.c, "f9925000.i2c"),
+	CLK_LOOKUP("iface_clk",           gcc_blsp1_ahb_clk.c, "f9927000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup1_i2c_apps_clk.c, "f9923000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup1_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup2_i2c_apps_clk.c, ""),
@@ -2882,7 +2886,7 @@
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup3_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup4_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup4_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk",  gcc_blsp1_qup5_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk",  gcc_blsp1_qup5_i2c_apps_clk.c, "f9927000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup5_spi_apps_clk.c, ""),
 	CLK_LOOKUP("iface_clk",           gcc_blsp1_ahb_clk.c, "f9928000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup6_i2c_apps_clk.c, "f9928000.i2c"),
@@ -2967,12 +2971,12 @@
 	CLK_LOOKUP("core_clk",                  vfe_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk",                  vfe_axi_clk.c, ""),
 
-	CLK_LOOKUP("core_clk",              csi0pix_mux_clk.c, ""),
-	CLK_LOOKUP("core_clk",              csi0phy_mux_clk.c, ""),
-	CLK_LOOKUP("core_clk",              csi1phy_mux_clk.c, ""),
-	CLK_LOOKUP("core_clk",                 rdi2_mux_clk.c, ""),
-	CLK_LOOKUP("core_clk",                 rdi1_mux_clk.c, ""),
-	CLK_LOOKUP("core_clk",                 rdi0_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",              csi0pix_cam_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",              csi0phy_cam_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",              csi1phy_cam_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",                 rdi2_cam_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",                 rdi1_cam_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",                 rdi0_cam_mux_clk.c, ""),
 
 	CLK_LOOKUP("core_clk",   oxili_gfx3d_clk.c, "fdc00000.qcom,kgsl-3d0"),
 	CLK_LOOKUP("iface_clk",    oxili_ahb_clk.c, "fdc00000.qcom,kgsl-3d0"),
@@ -3105,23 +3109,6 @@
 	.main_output_mask = BIT(0),
 };
 
-#define PLL_AUX_OUTPUT_BIT 1
-#define PLL_AUX2_OUTPUT_BIT 2
-
-#define PWR_ON_MASK		BIT(31)
-#define EN_REST_WAIT_MASK	(0xF << 20)
-#define EN_FEW_WAIT_MASK	(0xF << 16)
-#define CLK_DIS_WAIT_MASK	(0xF << 12)
-#define SW_OVERRIDE_MASK	BIT(2)
-#define HW_CONTROL_MASK		BIT(1)
-#define SW_COLLAPSE_MASK	BIT(0)
-
-/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
-#define EN_REST_WAIT_VAL	(0x2 << 20)
-#define EN_FEW_WAIT_VAL		(0x2 << 16)
-#define CLK_DIS_WAIT_VAL	(0x2 << 12)
-#define GDSC_TIMEOUT_US		50000
-
 static void __init reg_init(void)
 {
 	u32 regval;
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 9a614d8..4fb348d 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -645,7 +645,7 @@
 	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
 
 #define RPM_MISC_CLK_TYPE	0x306b6c63
 #define RPM_BUS_CLK_TYPE	0x316b6c63
@@ -4895,6 +4895,7 @@
 	CLK_LOOKUP("alt_iface_clk", mdss_hdmi_ahb_clk.c,
 		"fd922100.qcom,hdmi_tx"),
 	CLK_LOOKUP("core_clk", mdss_hdmi_clk.c, "fd922100.qcom,hdmi_tx"),
+	CLK_LOOKUP("mdp_core_clk", mdss_mdp_clk.c, "fd922100.qcom,hdmi_tx"),
 	CLK_LOOKUP("extp_clk", mdss_extpclk_clk.c, "fd922100.qcom,hdmi_tx"),
 	CLK_LOOKUP("core_clk", mdss_mdp_clk.c, "mdp.0"),
 	CLK_LOOKUP("lut_clk", mdss_mdp_lut_clk.c, "mdp.0"),
@@ -5355,20 +5356,6 @@
 	.main_output_mask = BIT(0),
 };
 
-#define PWR_ON_MASK		BIT(31)
-#define EN_REST_WAIT_MASK	(0xF << 20)
-#define EN_FEW_WAIT_MASK	(0xF << 16)
-#define CLK_DIS_WAIT_MASK	(0xF << 12)
-#define SW_OVERRIDE_MASK	BIT(2)
-#define HW_CONTROL_MASK		BIT(1)
-#define SW_COLLAPSE_MASK	BIT(0)
-
-/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
-#define EN_REST_WAIT_VAL	(0x2 << 20)
-#define EN_FEW_WAIT_VAL		(0x2 << 16)
-#define CLK_DIS_WAIT_VAL	(0x2 << 12)
-#define GDSC_TIMEOUT_US		50000
-
 static void __init reg_init(void)
 {
 	u32 regval;
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 65176b4..313e04c 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -287,7 +287,7 @@
 	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
 
 /* TODO: Needs to confirm the below values */
 #define RPM_MISC_CLK_TYPE	0x306b6c63
diff --git a/arch/arm/mach-msm/clock-generic.c b/arch/arm/mach-msm/clock-generic.c
new file mode 100644
index 0000000..4d74533
--- /dev/null
+++ b/arch/arm/mach-msm/clock-generic.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <linux/clk.h>
+#include <mach/clk-provider.h>
+#include <mach/clock-generic.h>
+
+/* ==================== Mux clock ==================== */
+
+static int parent_to_src_sel(struct mux_clk *mux, struct clk *p)
+{
+	int i;
+
+	for (i = 0; i < mux->num_parents; i++) {
+		if (mux->parents[i].src == p)
+			return mux->parents[i].sel;
+	}
+
+	return -EINVAL;
+}
+
+static int mux_set_parent(struct clk *c, struct clk *p)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	int sel = parent_to_src_sel(mux, p);
+	struct clk *old_parent;
+	int rc = 0;
+	unsigned long flags;
+
+	if (sel < 0)
+		return sel;
+
+	rc = __clk_pre_reparent(c, p, &flags);
+	if (rc)
+		goto out;
+
+	rc = mux->ops->set_mux_sel(mux, sel);
+	if (rc)
+		goto set_fail;
+
+	old_parent = c->parent;
+	c->parent = p;
+	__clk_post_reparent(c, old_parent, &flags);
+
+	return 0;
+
+set_fail:
+	__clk_post_reparent(c, p, &flags);
+out:
+	return rc;
+}
+
+static long mux_round_rate(struct clk *c, unsigned long rate)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	int i;
+	long prate, max_prate = 0, rrate = LONG_MAX;
+
+	for (i = 0; i < mux->num_parents; i++) {
+		prate = clk_round_rate(mux->parents[i].src, rate);
+		if (prate < rate) {
+			max_prate = max(prate, max_prate);
+			continue;
+		}
+
+		rrate = min(rrate, prate);
+	}
+	if (rrate == LONG_MAX)
+		rrate = max_prate;
+
+	return rrate ? rrate : -EINVAL;
+}
+
+static int mux_set_rate(struct clk *c, unsigned long rate)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	struct clk *new_parent = NULL;
+	int rc = 0, i;
+	unsigned long new_par_curr_rate;
+
+	for (i = 0; i < mux->num_parents; i++) {
+		if (clk_round_rate(mux->parents[i].src, rate) == rate) {
+			new_parent = mux->parents[i].src;
+			break;
+		}
+	}
+	if (new_parent == NULL)
+		return -EINVAL;
+
+	/*
+	 * Switch to safe parent since the old and new parent might be the
+	 * same and the parent might temporarily turn off while switching
+	 * rates.
+	 */
+	if (mux->safe_sel >= 0)
+		rc = mux->ops->set_mux_sel(mux, mux->safe_sel);
+	if (rc)
+		return rc;
+
+	new_par_curr_rate = clk_get_rate(new_parent);
+	rc = clk_set_rate(new_parent, rate);
+	if (rc)
+		goto set_rate_fail;
+
+	rc = mux_set_parent(c, new_parent);
+	if (rc)
+		goto set_par_fail;
+
+	return 0;
+
+set_par_fail:
+	clk_set_rate(new_parent, new_par_curr_rate);
+set_rate_fail:
+	WARN(mux->ops->set_mux_sel(mux, parent_to_src_sel(mux, c->parent)),
+		"Set rate failed for %s. Also in bad state!\n", c->dbg_name);
+	return rc;
+}
+
+static int mux_enable(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	if (mux->ops->enable)
+		return mux->ops->enable(mux);
+	return 0;
+}
+
+static void mux_disable(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	if (mux->ops->disable)
+		return mux->ops->disable(mux);
+}
+
+static struct clk *mux_get_parent(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	int sel = mux->ops->get_mux_sel(mux);
+	int i;
+
+	for (i = 0; i < mux->num_parents; i++) {
+		if (mux->parents[i].sel == sel)
+			return mux->parents[i].src;
+	}
+
+	/* Unfamiliar parent. */
+	return NULL;
+}
+
+static enum handoff mux_handoff(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+
+	c->rate = clk_get_rate(c->parent);
+	mux->safe_sel = parent_to_src_sel(mux, mux->safe_parent);
+
+	if (mux->en_mask && mux->ops && mux->ops->is_enabled)
+		return mux->ops->is_enabled(mux)
+			? HANDOFF_ENABLED_CLK
+			: HANDOFF_DISABLED_CLK;
+
+	/*
+	 * If this function returns 'enabled' even when the clock downstream
+	 * of this clock is disabled, then handoff code will unnecessarily
+	 * enable the current parent of this clock. If this function always
+	 * returns 'disabled' and a clock downstream is on, the clock handoff
+	 * code will bump up the ref count for this clock and its current
+	 * parent as necessary. So, clocks without an actual HW gate can
+	 * always return disabled.
+	 */
+	return HANDOFF_DISABLED_CLK;
+}
+
+struct clk_ops clk_ops_gen_mux = {
+	.enable = mux_enable,
+	.disable = mux_disable,
+	.set_parent = mux_set_parent,
+	.round_rate = mux_round_rate,
+	.set_rate = mux_set_rate,
+	.handoff = mux_handoff,
+	.get_parent = mux_get_parent,
+};
+
+
+/* ==================== Divider clock ==================== */
+
+static long __div_round_rate(struct clk *c, unsigned long rate, int *best_div)
+{
+	struct div_clk *d = to_div_clk(c);
+	unsigned int div, min_div, max_div;
+	long p_rrate, rrate = LONG_MAX;
+
+	rate = max(rate, 1UL);
+
+	if (!d->ops || !d->ops->set_div)
+		min_div = max_div = d->div;
+	else {
+		min_div = max(d->min_div, 1U);
+		max_div = min(d->max_div, (unsigned int) (LONG_MAX / rate));
+	}
+
+	for (div = min_div; div <= max_div; div++) {
+		p_rrate = clk_round_rate(c->parent, rate * div);
+		if (p_rrate < 0)
+			break;
+
+		p_rrate /= div;
+		/*
+		 * Trying higher dividers is only going to ask the parent for
+		 * a higher rate. If it can't even output a rate higher than
+		 * the one we request for this divider, the parent is not
+		 * going to be able to output an even higher rate required
+		 * for a higher divider. So, stop trying higher dividers.
+		 */
+		if (p_rrate < rate) {
+			if (rrate == LONG_MAX) {
+				rrate = p_rrate;
+				if (best_div)
+					*best_div = div;
+			}
+			break;
+		}
+		if (p_rrate < rrate) {
+			rrate = p_rrate;
+			if (best_div)
+				*best_div = div;
+		}
+
+		if (rrate <= rate + d->rate_margin)
+			break;
+	}
+
+	if (rrate == LONG_MAX)
+		return -EINVAL;
+
+	return rrate;
+}
+
+static long div_round_rate(struct clk *c, unsigned long rate)
+{
+	return __div_round_rate(c, rate, NULL);
+}
+
+static int div_set_rate(struct clk *c, unsigned long rate)
+{
+	struct div_clk *d = to_div_clk(c);
+	int div, rc = 0;
+	long rrate, old_prate;
+
+	rrate = __div_round_rate(c, rate, &div);
+	if (rrate != rate)
+		return -EINVAL;
+
+	if (div > d->div)
+		rc = d->ops->set_div(d, div);
+	if (rc)
+		return rc;
+
+	old_prate = clk_get_rate(c->parent);
+	rc = clk_set_rate(c->parent, rate * div);
+	if (rc)
+		goto set_rate_fail;
+
+	if (div < d->div)
+		rc = d->ops->set_div(d, div);
+	if (rc)
+		goto div_dec_fail;
+
+	d->div = div;
+
+	return 0;
+
+div_dec_fail:
+	WARN(clk_set_rate(c->parent, old_prate),
+		"Set rate failed for %s. Also in bad state!\n", c->dbg_name);
+set_rate_fail:
+	if (div > d->div)
+		WARN(d->ops->set_div(d, d->div),
+			"Set rate failed for %s. Also in bad state!\n",
+			c->dbg_name);
+	return rc;
+}
+
+static int div_enable(struct clk *c)
+{
+	struct div_clk *d = to_div_clk(c);
+	if (d->ops->enable)
+		return d->ops->enable(d);
+	return 0;
+}
+
+static void div_disable(struct clk *c)
+{
+	struct div_clk *d = to_div_clk(c);
+	if (d->ops->disable)
+		return d->ops->disable(d);
+}
+
+static enum handoff div_handoff(struct clk *c)
+{
+	struct div_clk *d = to_div_clk(c);
+
+	if (d->ops->get_div)
+		d->div = max(d->ops->get_div(d), 1);
+	d->div = max(d->div, 1U);
+	c->rate = clk_get_rate(c->parent) / d->div;
+
+	if (d->en_mask && d->ops && d->ops->is_enabled)
+		return d->ops->is_enabled(d)
+			? HANDOFF_ENABLED_CLK
+			: HANDOFF_DISABLED_CLK;
+
+	/*
+	 * If this function returns 'enabled' even when the clock downstream
+	 * of this clock is disabled, then handoff code will unnecessarily
+	 * enable the current parent of this clock. If this function always
+	 * returns 'disabled' and a clock downstream is on, the clock handoff
+	 * code will bump up the ref count for this clock and its current
+	 * parent as necessary. So, clocks without an actual HW gate can
+	 * always return disabled.
+	 */
+	return HANDOFF_DISABLED_CLK;
+}
+
+struct clk_ops clk_ops_div = {
+	.enable = div_enable,
+	.disable = div_disable,
+	.round_rate = div_round_rate,
+	.set_rate = div_set_rate,
+	.handoff = div_handoff,
+};
+
+static long __slave_div_round_rate(struct clk *c, unsigned long rate,
+					int *best_div)
+{
+	struct div_clk *d = to_div_clk(c);
+	unsigned int div, min_div, max_div;
+	long p_rate;
+
+	rate = max(rate, 1UL);
+
+	if (!d->ops || !d->ops->set_div)
+		min_div = max_div = d->div;
+	else {
+		min_div = d->min_div;
+		max_div = d->max_div;
+	}
+
+	p_rate = clk_get_rate(c->parent);
+	div = p_rate / rate;
+	div = max(div, min_div);
+	div = min(div, max_div);
+	if (best_div)
+		*best_div = div;
+
+	return p_rate / div;
+}
+
+static long slave_div_round_rate(struct clk *c, unsigned long rate)
+{
+	return __slave_div_round_rate(c, rate, NULL);
+}
+
+static int slave_div_set_rate(struct clk *c, unsigned long rate)
+{
+	struct div_clk *d = to_div_clk(c);
+	int div, rc = 0;
+	long rrate;
+
+	rrate = __slave_div_round_rate(c, rate, &div);
+	if (rrate != rate)
+		return -EINVAL;
+
+	if (div == d->div)
+		return 0;
+
+	if (d->ops->set_div)
+		rc = d->ops->set_div(d, div);
+	if (rc)
+		return rc;
+
+	d->div = div;
+
+	return 0;
+}
+
+struct clk_ops clk_ops_slave_div = {
+	.enable = div_enable,
+	.disable = div_disable,
+	.round_rate = slave_div_round_rate,
+	.set_rate = slave_div_set_rate,
+	.handoff = div_handoff,
+};
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 8915bad..e67d973 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -815,18 +815,18 @@
 /*
  * mux clock functions
  */
-static void mux_clk_halt_check(void)
+static void cam_mux_clk_halt_check(void)
 {
 	/* Ensure that the delay starts after the mux disable/enable. */
 	mb();
 	udelay(HALT_CHECK_DELAY_US);
 }
 
-static int mux_clk_enable(struct clk *c)
+static int cam_mux_clk_enable(struct clk *c)
 {
 	unsigned long flags;
 	u32 regval;
-	struct mux_clk *mux = to_mux_clk(c);
+	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 
 	spin_lock_irqsave(&local_clock_reg_lock, flags);
 	regval = readl_relaxed(ENABLE_REG(mux));
@@ -835,15 +835,15 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 
 	/* Wait for clock to enable before continuing. */
-	mux_clk_halt_check();
+	cam_mux_clk_halt_check();
 
 	return 0;
 }
 
-static void mux_clk_disable(struct clk *c)
+static void cam_mux_clk_disable(struct clk *c)
 {
 	unsigned long flags;
-	struct mux_clk *mux = to_mux_clk(c);
+	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 	u32 regval;
 
 	spin_lock_irqsave(&local_clock_reg_lock, flags);
@@ -853,10 +853,10 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 
 	/* Wait for clock to disable before continuing. */
-	mux_clk_halt_check();
+	cam_mux_clk_halt_check();
 }
 
-static int mux_source_switch(struct mux_clk *mux, struct mux_source *dest)
+static int mux_source_switch(struct cam_mux_clk *mux, struct mux_source *dest)
 {
 	unsigned long flags;
 	u32 regval;
@@ -879,9 +879,9 @@
 	return ret;
 }
 
-static int mux_clk_set_parent(struct clk *c, struct clk *parent)
+static int cam_mux_clk_set_parent(struct clk *c, struct clk *parent)
 {
-	struct mux_clk *mux = to_mux_clk(c);
+	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 	struct mux_source *dest = NULL;
 	int ret;
 
@@ -908,9 +908,9 @@
 	return 0;
 }
 
-static enum handoff mux_clk_handoff(struct clk *c)
+static enum handoff cam_mux_clk_handoff(struct clk *c)
 {
-	struct mux_clk *mux = to_mux_clk(c);
+	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 	u32 mask = mux->enable_mask;
 	u32 regval = readl_relaxed(ENABLE_REG(mux));
 
@@ -922,9 +922,9 @@
 	return HANDOFF_DISABLED_CLK;
 }
 
-static struct clk *mux_clk_get_parent(struct clk *c)
+static struct clk *cam_mux_clk_get_parent(struct clk *c)
 {
-	struct mux_clk *mux = to_mux_clk(c);
+	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 	struct mux_source *parent = NULL;
 	u32 regval = readl_relaxed(SELECT_REG(mux));
 
@@ -943,9 +943,9 @@
 	return ERR_PTR(-EPERM);
 }
 
-static int mux_clk_list_rate(struct clk *c, unsigned n)
+static int cam_mux_clk_list_rate(struct clk *c, unsigned n)
 {
-	struct mux_clk *mux = to_mux_clk(c);
+	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 	int i;
 
 	for (i = 0; i < n; i++)
@@ -1022,13 +1022,13 @@
 	.handoff = local_vote_clk_handoff,
 };
 
-struct clk_ops clk_ops_mux = {
-	.enable = mux_clk_enable,
-	.disable = mux_clk_disable,
-	.set_parent = mux_clk_set_parent,
-	.get_parent = mux_clk_get_parent,
-	.handoff = mux_clk_handoff,
-	.list_rate = mux_clk_list_rate,
+struct clk_ops clk_ops_cam_mux = {
+	.enable = cam_mux_clk_enable,
+	.disable = cam_mux_clk_disable,
+	.set_parent = cam_mux_clk_set_parent,
+	.get_parent = cam_mux_clk_get_parent,
+	.handoff = cam_mux_clk_handoff,
+	.list_rate = cam_mux_clk_list_rate,
 };
 
 
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
index f33cf9c..f307a2f 100644
--- a/arch/arm/mach-msm/clock-local2.h
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -163,7 +163,7 @@
 };
 
 /**
- * struct mux_clk - branch clock
+ * struct cam_mux_clk - branch clock
  * @c: clk
  * @enable_reg: register that contains the enable bit(s) for the mux
  * @select_reg: register that contains the source selection bits for the mux
@@ -172,7 +172,7 @@
  * @sources: list of mux sources
  * @base: pointer to base address of ioremapped registers.
  */
-struct mux_clk {
+struct cam_mux_clk {
 	struct clk c;
 	const u32 enable_reg;
 	const u32 select_reg;
@@ -184,9 +184,9 @@
 	void *const __iomem *base;
 };
 
-static inline struct mux_clk *to_mux_clk(struct clk *clk)
+static inline struct cam_mux_clk *to_cam_mux_clk(struct clk *clk)
 {
-	return container_of(clk, struct mux_clk, c);
+	return container_of(clk, struct cam_mux_clk, c);
 }
 
 /*
@@ -200,7 +200,7 @@
  */
 extern spinlock_t local_clock_reg_lock;
 
-extern struct clk_ops clk_ops_mux;
+extern struct clk_ops clk_ops_cam_mux;
 extern struct clk_ops clk_ops_empty;
 extern struct clk_ops clk_ops_rcg;
 extern struct clk_ops clk_ops_rcg_mnd;
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 2e12e27..08817c0 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -63,6 +63,7 @@
 	int level, rc = 0, i;
 	struct regulator **r = vdd_class->regulator;
 	int **vdd_uv = vdd_class->vdd_uv;
+	int **vdd_ua = vdd_class->vdd_ua;
 	int max_level = vdd_class->num_levels - 1;
 
 	for (level = max_level; level > 0; level--)
@@ -77,20 +78,36 @@
 			vdd_uv[max_level][i]);
 		if (rc)
 			goto set_voltage_fail;
+
+		if (!vdd_ua)
+			continue;
+
+		rc = regulator_set_optimum_mode(r[i], vdd_ua[level][i]);
+		if (rc < 0)
+			goto set_mode_fail;
 	}
 	if (vdd_class->set_vdd && !vdd_class->num_regulators)
 		rc = vdd_class->set_vdd(vdd_class, level);
 
-	if (!rc)
+	if (rc < 0)
 		vdd_class->cur_level = level;
 
-	return rc;
+	return 0;
+
+set_mode_fail:
+	regulator_set_voltage(r[i], vdd_uv[vdd_class->cur_level][i],
+				vdd_uv[max_level][i]);
 
 set_voltage_fail:
-	level = vdd_class->cur_level;
-	for (i--; i >= 0; i--)
-		regulator_set_voltage(r[i], vdd_uv[level][i],
-			vdd_uv[max_level][i]);
+	for (i--; i >= 0; i--) {
+		regulator_set_voltage(r[i], vdd_uv[vdd_class->cur_level][i],
+					vdd_uv[max_level][i]);
+
+		if (!vdd_ua)
+			continue;
+		regulator_set_optimum_mode(r[i],
+					vdd_ua[vdd_class->cur_level][i]);
+	}
 
 	return rc;
 }
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index b358b53..0dd4957 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -49,6 +49,8 @@
  * @set_vdd: function to call when applying a new voltage setting.
  * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
 		regulator.
+ * @vdd_ua: sorted 2D array of legal cureent settings. Indexed by level, then
+		regulator. Optional parameter.
  * @level_votes: array of votes for each level.
  * @num_levels: specifies the size of level_votes array.
  * @cur_level: the currently set voltage level
@@ -60,6 +62,7 @@
 	int num_regulators;
 	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
 	int **vdd_uv;
+	int **vdd_ua;
 	int *level_votes;
 	int num_levels;
 	unsigned long cur_level;
@@ -76,10 +79,12 @@
 		.lock = __MUTEX_INITIALIZER(_name.lock) \
 	}
 
-#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv) \
+#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv, \
+	 _vdd_ua) \
 	struct clk_vdd_class _name = { \
 		.class_name = #_name, \
 		.vdd_uv = _vdd_uv, \
+		.vdd_ua = _vdd_ua, \
 		.regulator = (struct regulator * [_num_regulators]) {}, \
 		.num_regulators = _num_regulators, \
 		.level_votes = (int [_num_levels]) {}, \
@@ -89,6 +94,7 @@
 	}
 
 #define VDD_UV(...) ((int []){__VA_ARGS__})
+#define VDD_UA(...) ((int []){__VA_ARGS__})
 
 enum handoff {
 	HANDOFF_ENABLED_CLK,
diff --git a/arch/arm/mach-msm/include/mach/clock-generic.h b/arch/arm/mach-msm/include/mach/clock-generic.h
new file mode 100644
index 0000000..0f689f1
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/clock-generic.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_CLOCK_GENERIC_H
+#define __MACH_CLOCK_GENERIC_H
+
+#include <mach/clk-provider.h>
+
+/* ==================== Mux clock ==================== */
+
+struct clk_src {
+	struct clk *src;
+	int sel;
+};
+
+struct mux_clk;
+
+struct clk_mux_ops {
+	int (*set_mux_sel)(struct mux_clk *clk, int sel);
+	int (*get_mux_sel)(struct mux_clk *clk);
+
+	/* Optional */
+	bool (*is_enabled)(struct mux_clk *clk);
+	int (*enable)(struct mux_clk *clk);
+	void (*disable)(struct mux_clk *clk);
+};
+
+#define MUX_SRC_LIST(...) \
+	.parents = (struct clk_src[]){__VA_ARGS__}, \
+	.num_parents = ARRAY_SIZE(((struct clk_src[]){__VA_ARGS__}))
+
+struct mux_clk {
+	/* Parents in decreasing order of preference for obtaining rates. */
+	struct clk_src	*parents;
+	int		num_parents;
+	struct clk	*safe_parent;
+	int		safe_sel;
+	struct clk_mux_ops *ops;
+
+	/* Fields not used by helper function. */
+	void *const __iomem *base;
+	u32		offset;
+	u32		mask;
+	u32		shift;
+	u32		en_mask;
+	void		*priv;
+
+	struct clk	c;
+};
+
+static inline struct mux_clk *to_mux_clk(struct clk *c)
+{
+	return container_of(c, struct mux_clk, c);
+}
+
+extern struct clk_ops clk_ops_gen_mux;
+
+/* ==================== Divider clock ==================== */
+
+struct div_clk;
+
+struct clk_div_ops {
+	int (*set_div)(struct div_clk *clk, int div);
+	int (*get_div)(struct div_clk *clk);
+
+	/* Optional */
+	bool (*is_enabled)(struct div_clk *clk);
+	int (*enable)(struct div_clk *clk);
+	void (*disable)(struct div_clk *clk);
+};
+
+struct div_clk {
+	unsigned int	div;
+	unsigned int	min_div;
+	unsigned int	max_div;
+	unsigned long	rate_margin;
+	struct clk_div_ops *ops;
+
+	/* Fields not used by helper function. */
+	void *const __iomem *base;
+	u32		offset;
+	u32		mask;
+	u32		shift;
+	u32		en_mask;
+	void		*priv;
+	struct clk	c;
+};
+
+static inline struct div_clk *to_div_clk(struct clk *c)
+{
+	return container_of(c, struct div_clk, c);
+}
+
+extern struct clk_ops clk_ops_div;
+extern struct clk_ops clk_ops_slave_div;
+
+#define DEFINE_FIXED_DIV_CLK(clk_name, _div, _parent) \
+static struct div_clk clk_name = {	\
+	.div = _div,				\
+	.c = {					\
+		.parent = _parent,		\
+		.dbg_name = #clk_name,		\
+		.ops = &clk_ops_div,		\
+		CLK_INIT(clk_name.c),		\
+	}					\
+}
+
+#define DEFINE_FIXED_SLAVE_DIV_CLK(clk_name, _div, _parent) \
+static struct div_clk clk_name = {	\
+	.div = _div,				\
+	.c = {					\
+		.parent = _parent,		\
+		.dbg_name = #clk_name,		\
+		.ops = &clk_ops_slave_div,		\
+		CLK_INIT(clk_name.c),		\
+	}					\
+}
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/ecm_ipa.h b/arch/arm/mach-msm/include/mach/ecm_ipa.h
index 008a659..f6afb2a 100644
--- a/arch/arm/mach-msm/include/mach/ecm_ipa.h
+++ b/arch/arm/mach-msm/include/mach/ecm_ipa.h
@@ -24,15 +24,35 @@
 		enum ipa_dp_evt_type evt,
 		unsigned long data);
 
+/*
+ * struct ecm_ipa_params - parameters for ecm_ipa initialization API
+ *
+ * @ecm_ipa_rx_dp_notify: ecm_ipa will set this callback (out parameter).
+ * this callback shall be supplied for ipa_connect upon pipe
+ * connection (USB->IPA), once IPA driver receive data packets
+ * from USB pipe destined for Apps this callback will be called.
+ * @ecm_ipa_tx_dp_notify: ecm_ipa will set this callback (out parameter).
+ * this callback shall be supplied for ipa_connect upon pipe
+ * connection (IPA->USB), once IPA driver send packets destined
+ * for USB, IPA BAM will notify for Tx-complete.
+ * @priv: ecm_ipa will set this pointer (out parameter).
+ * This pointer will hold the network device for later interaction
+ * with ecm_ipa APIs
+ * @host_ethaddr: host Ethernet address in network order
+ * @device_ethaddr: device Ethernet address in network order
+ */
+struct ecm_ipa_params {
+	ecm_ipa_callback ecm_ipa_rx_dp_notify;
+	ecm_ipa_callback ecm_ipa_tx_dp_notify;
+	u8 host_ethaddr[ETH_ALEN];
+	u8 device_ethaddr[ETH_ALEN];
+	void *private;
+};
+
 
 #ifdef CONFIG_ECM_IPA
 
-int ecm_ipa_init(ecm_ipa_callback * ecm_ipa_rx_dp_notify,
-		ecm_ipa_callback * ecm_ipa_tx_dp_notify,
-		void **priv);
-
-int ecm_ipa_configure(u8 host_ethaddr[], u8 device_ethaddr[],
-		void *priv);
+int ecm_ipa_init(struct ecm_ipa_params *params);
 
 int ecm_ipa_connect(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl,
 		void *priv);
@@ -43,15 +63,7 @@
 
 #else /* CONFIG_ECM_IPA*/
 
-static inline int ecm_ipa_init(ecm_ipa_callback *ecm_ipa_rx_dp_notify,
-		ecm_ipa_callback *ecm_ipa_tx_dp_notify,
-		void **priv)
-{
-	return 0;
-}
-
-static inline int ecm_ipa_configure(u8 host_ethaddr[], u8 device_ethaddr[],
-		void *priv)
+int ecm_ipa_init(struct ecm_ipa_params *params)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index b4fbaee..db5e126 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -464,6 +464,13 @@
 int ipa_disconnect(u32 clnt_hdl);
 
 /*
+ * Resume / Suspend
+ */
+int ipa_resume(u32 clnt_hdl);
+
+int ipa_suspend(u32 clnt_hdl);
+
+/*
  * Configuration
  */
 int ipa_cfg_ep(u32 clnt_hdl, const struct ipa_ep_cfg *ipa_ep_cfg);
@@ -696,6 +703,19 @@
 }
 
 /*
+ * Resume / Suspend
+ */
+static inline int ipa_resume(u32 clnt_hdl)
+{
+	return -EPERM;
+}
+
+static inline int ipa_suspend(u32 clnt_hdl)
+{
+	return -EPERM;
+}
+
+/*
  * Configuration
  */
 static inline int ipa_cfg_ep(u32 clnt_hdl,
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 008ecea..64531f0 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -36,11 +36,14 @@
 #define of_board_is_rumi()	of_machine_is_compatible("qcom,rumi")
 #define of_board_is_fluid()	of_machine_is_compatible("qcom,fluid")
 #define of_board_is_liquid()	of_machine_is_compatible("qcom,liquid")
+#define of_board_is_dragonboard()	\
+	of_machine_is_compatible("qcom,dragonboard")
 
 #define machine_is_msm8974()	of_machine_is_compatible("qcom,msm8974")
 #define machine_is_msm9625()	of_machine_is_compatible("qcom,msm9625")
 #define machine_is_msm8610()	of_machine_is_compatible("qcom,msm8610")
 #define machine_is_msm8226()	of_machine_is_compatible("qcom,msm8226")
+#define machine_is_apq8074()	of_machine_is_compatible("qcom,apq8074")
 
 #define early_machine_is_msm8610()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
@@ -55,11 +58,13 @@
 #define of_board_is_rumi()		0
 #define of_board_is_fluid()		0
 #define of_board_is_liquid()		0
+#define of_board_is_dragonboard()	0
 
 #define machine_is_msm8974()		0
 #define machine_is_msm9625()		0
 #define machine_is_msm8610()		0
 #define machine_is_msm8226()		0
+#define machine_is_apq8074()		0
 
 #define early_machine_is_msm8610()	0
 #define early_machine_is_mpq8092()	0
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 4d4703f..893db0b 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,7 @@
  * @powerup: Start a subsystem
  * @crash_shutdown: Shutdown a subsystem when the system crashes (can't sleep)
  * @ramdump: Collect a ramdump of the subsystem
+ * @is_loadable: Indicate if subsystem firmware is loadable via pil framework
  */
 struct subsys_desc {
 	const char *name;
@@ -56,6 +57,7 @@
 	void (*crash_shutdown)(const struct subsys_desc *desc);
 	int (*ramdump)(int, const struct subsys_desc *desc);
 	unsigned int err_ready_irq;
+	int is_loadable;
 };
 
 #if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 4ed4eda..9b18c59 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -66,7 +66,7 @@
 #define NUM_PORTS_SHIFT (0)
 #define GFX_MPU_SHIFT (12)
 
-#define NUM_MACROS_MASK (0xF << 8)
+#define NUM_MACROS_MASK (0x3F << 8)
 #define NUM_MACROS_SHIFT (8)
 
 #define INTERLEAVING_MASK (0x1 << 17)
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index cf29cf1..b186a4d 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -515,6 +515,17 @@
 	drv->subsys_desc.start = pronto_start;
 	drv->subsys_desc.stop = pronto_stop;
 
+	ret = of_get_named_gpio(pdev->dev.of_node,
+			"qcom,gpio-err-ready", 0);
+	if (ret < 0)
+		return ret;
+
+	ret = gpio_to_irq(ret);
+	if (ret < 0)
+		return ret;
+
+	drv->subsys_desc.err_ready_irq = ret;
+
 	INIT_DELAYED_WORK(&drv->cancel_vote_work, wcnss_post_bootup);
 
 	drv->subsys = subsys_register(&drv->subsys_desc);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 3ce1283..e993282 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -92,7 +92,6 @@
 	void *smem_ramdump_dev;
 	bool crash_shutdown;
 	bool ignore_errors;
-	int is_loadable;
 	int err_fatal_irq;
 	int force_stop_gpio;
 };
@@ -502,7 +501,7 @@
 {
 	struct mba_data *drv = subsys_to_drv(subsys);
 
-	if (!drv->is_loadable)
+	if (!subsys->is_loadable)
 		return 0;
 	pil_shutdown(&drv->desc);
 	pil_shutdown(&drv->q6->desc);
@@ -514,7 +513,7 @@
 	struct mba_data *drv = subsys_to_drv(subsys);
 	int ret;
 
-	if (!drv->is_loadable)
+	if (!subsys->is_loadable)
 		return 0;
 	/*
 	 * At this time, the modem is shutdown. Therefore this function cannot
@@ -601,7 +600,7 @@
 	int ret;
 	struct mba_data *drv = subsys_to_drv(desc);
 
-	if (!drv->is_loadable)
+	if (!desc->is_loadable)
 		return 0;
 
 	ret = pil_boot(&drv->q6->desc);
@@ -624,7 +623,7 @@
 {
 	struct mba_data *drv = subsys_to_drv(desc);
 
-	if (!drv->is_loadable)
+	if (!desc->is_loadable)
 		return;
 
 	pil_shutdown(&drv->desc);
@@ -826,16 +825,17 @@
 static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
 {
 	struct mba_data *drv;
-	int ret, err_fatal_gpio;
+	int ret, err_fatal_gpio, is_loadable;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
 		return -ENOMEM;
 	platform_set_drvdata(pdev, drv);
 
-	drv->is_loadable = of_property_read_bool(pdev->dev.of_node,
+	is_loadable = of_property_read_bool(pdev->dev.of_node,
 							"qcom,is-loadable");
-	if (drv->is_loadable) {
+	if (is_loadable) {
+		drv->subsys_desc.is_loadable = 1;
 		ret = pil_mss_loadable_init(drv, pdev);
 		if (ret)
 			return ret;
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/version_b/q6usm_b.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/version_b/q6usm_b.c
index ff7ba33..a3af3e78 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/version_b/q6usm_b.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/version_b/q6usm_b.c
@@ -17,7 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
-#include <sound/apr_audio.h>
+#include <sound/apr_audio-v2.h>
 #include <mach/qdsp6v2/apr_us_b.h>
 #include "q6usm.h"
 
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index fb44e16..9479d46c 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -495,6 +495,9 @@
 	if (ret)
 		return ret;
 
+	if (!subsys->desc->is_loadable)
+		return 0;
+
 	ret = wait_for_err_ready(subsys);
 	if (ret)
 		/* pil-boot succeeded but we need to shutdown
diff --git a/block/blk-core.c b/block/blk-core.c
index 69764df..2b6595c 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1123,7 +1123,7 @@
 		 * urgent requests. We want to be able to track this
 		 * down.
 		 */
-		pr_err("%s(): requeueing an URGENT request", __func__);
+		pr_err("%s(): reinserting an URGENT request", __func__);
 		WARN_ON(!q->dispatched_urgent);
 		q->dispatched_urgent = false;
 	}
@@ -2018,6 +2018,10 @@
 			 * not be passed by new incoming requests
 			 */
 			rq->cmd_flags |= REQ_STARTED;
+			if (rq->cmd_flags & REQ_URGENT) {
+				WARN_ON(q->dispatched_urgent);
+				q->dispatched_urgent = true;
+			}
 			trace_block_rq_issue(q, rq);
 		}
 
@@ -2151,13 +2155,8 @@
 	struct request *rq;
 
 	rq = blk_peek_request(q);
-	if (rq) {
-		if (rq->cmd_flags & REQ_URGENT) {
-			WARN_ON(q->dispatched_urgent);
-			q->dispatched_urgent = true;
-		}
+	if (rq)
 		blk_start_request(rq);
-	}
 	return rq;
 }
 EXPORT_SYMBOL(blk_fetch_request);
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index d9f81b0..58fa5c9 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -3438,6 +3438,9 @@
 	if (handle == NULL)
 		return -ENODEV;
 
+	qce_enable_clk(pce_dev);
+	qce_sps_exit(pce_dev);
+
 	if (pce_dev->iobase)
 		iounmap(pce_dev->iobase);
 	if (pce_dev->coh_vmem)
@@ -3447,7 +3450,6 @@
 	qce_disable_clk(pce_dev);
 	__qce_deinit_clk(pce_dev);
 
-	qce_sps_exit(pce_dev);
 	kfree(handle);
 
 	return 0;
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 7666e74..a09bb42 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -323,10 +323,10 @@
 	u32 qcedev_sha_fail;
 };
 
-static struct qcedev_stat _qcedev_stat[MAX_QCE_DEVICE];
+static struct qcedev_stat _qcedev_stat;
 static struct dentry *_debug_dent;
 static char _debug_read_buf[DEBUG_MAX_RW_BUF];
-static int _debug_qcedev[MAX_QCE_DEVICE];
+static int _debug_qcedev;
 
 static struct qcedev_control *qcedev_minor_to_control(unsigned n)
 {
@@ -693,7 +693,7 @@
 	if (ret)
 		qcedev_areq->err = -EIO;
 
-	pstat = &_qcedev_stat[podev->pdev->id];
+	pstat = &_qcedev_stat;
 	if (qcedev_areq->op_type == QCEDEV_CRYPTO_OPER_CIPHER) {
 		switch (qcedev_areq->cipher_op_req.op) {
 		case QCEDEV_OPER_DEC:
@@ -1739,7 +1739,7 @@
 		return -ENOTTY;
 
 	init_completion(&qcedev_areq.complete);
-	pstat = &_qcedev_stat[podev->pdev->id];
+	pstat = &_qcedev_stat;
 
 	switch (cmd) {
 	case QCEDEV_IOCTL_LOCK_CE:
@@ -2026,11 +2026,7 @@
 	struct qcedev_stat *pstat;
 	int len = 0;
 
-	if (id < 0) {
-		pr_err("Crypto id is %d, cannot be negative\n", id);
-		return len;
-	}
-	pstat = &_qcedev_stat[id];
+	pstat = &_qcedev_stat;
 	len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
 			"\nQualcomm QCE dev driver %d Statistics:\n",
 				id + 1);
@@ -2076,10 +2072,7 @@
 static ssize_t _debug_stats_write(struct file *file, const char __user *buf,
 			size_t count, loff_t *ppos)
 {
-
-	int qcedev = *((int *) file->private_data);
-
-	memset((char *)&_qcedev_stat[qcedev], 0, sizeof(struct qcedev_stat));
+	memset((char *)&_qcedev_stat, 0, sizeof(struct qcedev_stat));
 	return count;
 };
 
@@ -2093,7 +2086,6 @@
 {
 	int rc;
 	char name[DEBUG_MAX_FNAME];
-	int i;
 	struct dentry *dent;
 
 	_debug_dent = debugfs_create_dir("qcedev", NULL);
@@ -2103,17 +2095,15 @@
 		return PTR_ERR(_debug_dent);
 	}
 
-	for (i = 0; i < MAX_QCE_DEVICE; i++) {
-		snprintf(name, DEBUG_MAX_FNAME-1, "stats-%d", i+1);
-		_debug_qcedev[i] = i;
-		dent = debugfs_create_file(name, 0644, _debug_dent,
-				&_debug_qcedev[i], &_debug_stats_ops);
-		if (dent == NULL) {
-			pr_err("qcedev debugfs_create_file fail, error %ld\n",
-					PTR_ERR(dent));
-			rc = PTR_ERR(dent);
-			goto err;
-		}
+	snprintf(name, DEBUG_MAX_FNAME-1, "stats-%d", 1);
+	_debug_qcedev = 0;
+	dent = debugfs_create_file(name, 0644, _debug_dent,
+			&_debug_qcedev, &_debug_stats_ops);
+	if (dent == NULL) {
+		pr_err("qcedev debugfs_create_file fail, error %ld\n",
+				PTR_ERR(dent));
+		rc = PTR_ERR(dent);
+		goto err;
 	}
 	return 0;
 err:
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 40fb29ac..d1cb933 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -42,7 +42,6 @@
 #include "qce.h"
 
 
-#define MAX_CRYPTO_DEVICE 3
 #define DEBUG_MAX_FNAME  16
 #define DEBUG_MAX_RW_BUF 1024
 
@@ -53,6 +52,8 @@
 	u32 aead_sha1_des_dec;
 	u32 aead_sha1_3des_enc;
 	u32 aead_sha1_3des_dec;
+	u32 aead_ccm_aes_enc;
+	u32 aead_ccm_aes_dec;
 	u32 aead_op_success;
 	u32 aead_op_fail;
 	u32 ablk_cipher_aes_enc;
@@ -72,7 +73,7 @@
 	u32 sha_hmac_op_success;
 	u32 sha_hmac_op_fail;
 };
-static struct crypto_stat _qcrypto_stat[MAX_CRYPTO_DEVICE];
+static struct crypto_stat _qcrypto_stat;
 static struct dentry *_debug_dent;
 static char _debug_read_buf[DEBUG_MAX_RW_BUF];
 
@@ -405,6 +406,39 @@
 	return i;
 }
 
+size_t qcrypto_sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
+			   void *buf, size_t buflen)
+{
+	int i;
+	size_t offset, len;
+
+	for (i = 0, offset = 0; i < nents; ++i) {
+		len = sg_copy_from_buffer(sgl, 1, buf, buflen);
+		buf += len;
+		buflen -= len;
+		offset += len;
+		sgl = scatterwalk_sg_next(sgl);
+	}
+
+	return offset;
+}
+
+size_t qcrypto_sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+			 void *buf, size_t buflen)
+{
+	int i;
+	size_t offset, len;
+
+	for (i = 0, offset = 0; i < nents; ++i) {
+		len = sg_copy_to_buffer(sgl, 1, buf, buflen);
+		buf += len;
+		buflen -= len;
+		offset += len;
+		sgl = scatterwalk_sg_next(sgl);
+	}
+
+	return offset;
+}
 static struct qcrypto_alg *_qcrypto_sha_alg_alloc(struct crypto_priv *cp,
 		struct ahash_alg *template)
 {
@@ -581,11 +615,7 @@
 	struct crypto_stat *pstat;
 	int len = 0;
 
-	if (id < 0) {
-		pr_err("Crypto id is %d, cannot be negative\n", id);
-		return len;
-	}
-	pstat = &_qcrypto_stat[id];
+	pstat = &_qcrypto_stat;
 	len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
 			"\nQualcomm crypto accelerator %d Statistics:\n",
 				id + 1);
@@ -641,6 +671,13 @@
 					pstat->aead_sha1_3des_dec);
 
 	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+			"   AEAD CCM-AES encryption     : %d\n",
+					pstat->aead_ccm_aes_enc);
+	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
+			"   AEAD CCM-AES decryption     : %d\n",
+					pstat->aead_ccm_aes_dec);
+
+	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   AEAD operation success       : %d\n",
 					pstat->aead_op_success);
 	len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
@@ -858,7 +895,7 @@
 	uint32_t diglen = crypto_ahash_digestsize(ahash);
 	uint32_t *auth32 = (uint32_t *)authdata;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 #ifdef QCRYPTO_DEBUG
 	dev_info(&cp->pdev->dev, "_qce_ahash_complete: %p ret %d\n",
@@ -916,7 +953,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 #ifdef QCRYPTO_DEBUG
 	dev_info(&cp->pdev->dev, "_qce_ablk_cipher_complete: %p ret %d\n",
@@ -943,7 +980,7 @@
 		areq->dst = rctx->orig_dst;
 
 		num_sg = qcrypto_count_sg(areq->dst, areq->nbytes);
-		bytes = sg_copy_from_buffer(areq->dst, num_sg,
+		bytes = qcrypto_sg_copy_from_buffer(areq->dst, num_sg,
 			rctx->data, areq->nbytes);
 		if (bytes != areq->nbytes)
 			pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes,
@@ -967,7 +1004,7 @@
 	struct qcrypto_cipher_req_ctx *rctx;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(areq);
 
@@ -988,7 +1025,7 @@
 				nbytes = areq->cryptlen -
 						crypto_aead_authsize(aead);
 			num_sg = qcrypto_count_sg(areq->dst, nbytes);
-			bytes = sg_copy_from_buffer(areq->dst, num_sg,
+			bytes = qcrypto_sg_copy_from_buffer(areq->dst, num_sg,
 					((char *)rctx->data + areq->assoclen),
 					nbytes);
 			if (bytes != nbytes)
@@ -1118,7 +1155,7 @@
 	qreq->assoclen = ALIGN((alen + len), 16);
 
 	num_sg = qcrypto_count_sg(sg, alen);
-	bytes = sg_copy_to_buffer(sg, num_sg, adata, alen);
+	bytes = qcrypto_sg_copy_to_buffer(sg, num_sg, adata, alen);
 	if (bytes != alen)
 		pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes, alen);
 
@@ -1145,7 +1182,7 @@
 
 		rctx->orig_src = req->src;
 		rctx->orig_dst = req->dst;
-		rctx->data = kzalloc((req->nbytes + 64), GFP_KERNEL);
+		rctx->data = kzalloc((req->nbytes + 64), GFP_ATOMIC);
 
 		if (rctx->data == NULL) {
 			pr_err("Mem Alloc fail rctx->data, err %ld for 0x%x\n",
@@ -1153,7 +1190,7 @@
 			return -ENOMEM;
 		}
 		num_sg = qcrypto_count_sg(req->src, req->nbytes);
-		bytes = sg_copy_to_buffer(req->src, num_sg, rctx->data,
+		bytes = qcrypto_sg_copy_to_buffer(req->src, num_sg, rctx->data,
 								req->nbytes);
 		if (bytes != req->nbytes)
 			pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes,
@@ -1294,7 +1331,7 @@
 			rctx->orig_src = req->src;
 			rctx->orig_dst = req->dst;
 			rctx->data = kzalloc((req->cryptlen + qreq.assoclen +
-					qreq.authsize + 64*2), GFP_KERNEL);
+					qreq.authsize + 64*2), GFP_ATOMIC);
 			if (rctx->data == NULL) {
 				pr_err("Mem Alloc fail rctx->data, err %ld\n",
 							PTR_ERR(rctx->data));
@@ -1305,7 +1342,7 @@
 			memcpy((char *)rctx->data, qreq.assoc, qreq.assoclen);
 
 			num_sg = qcrypto_count_sg(req->src, req->cryptlen);
-			bytes = sg_copy_to_buffer(req->src, num_sg,
+			bytes = qcrypto_sg_copy_to_buffer(req->src, num_sg,
 				rctx->data + qreq.assoclen , req->cryptlen);
 			if (bytes != req->cryptlen)
 				pr_warn("bytes copied=0x%x bytes to copy= 0x%x",
@@ -1358,7 +1395,7 @@
 	int ret = 0;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 again:
 	spin_lock_irqsave(&cp->lock, flags);
@@ -1434,7 +1471,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1458,7 +1495,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1482,7 +1519,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1506,7 +1543,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1533,7 +1570,7 @@
 		(ctx->auth_key_len != AES_KEYSIZE_256))
 		return  -EINVAL;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -1542,7 +1579,7 @@
 	rctx->mode = QCE_MODE_CCM;
 	rctx->iv = req->iv;
 
-	pstat->aead_sha1_aes_enc++;
+	pstat->aead_ccm_aes_enc++;
 	return _qcrypto_queue_req(cp, &req->base);
 }
 
@@ -1553,7 +1590,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1574,7 +1611,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1595,7 +1632,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1616,7 +1653,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1637,7 +1674,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1661,7 +1698,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1686,7 +1723,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1712,7 +1749,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1733,7 +1770,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1754,7 +1791,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1775,7 +1812,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1796,7 +1833,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
@@ -1824,7 +1861,7 @@
 		(ctx->auth_key_len != AES_KEYSIZE_256))
 		return  -EINVAL;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -1833,7 +1870,7 @@
 	rctx->mode = QCE_MODE_CCM;
 	rctx->iv = req->iv;
 
-	pstat->aead_sha1_aes_dec++;
+	pstat->aead_ccm_aes_dec++;
 	return _qcrypto_queue_req(cp, &req->base);
 }
 
@@ -1939,7 +1976,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 #ifdef QCRYPTO_DEBUG
 	dev_info(&cp->pdev->dev, "_qcrypto_aead_encrypt_aes_cbc: %p\n", req);
@@ -1963,7 +2000,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 #ifdef QCRYPTO_DEBUG
 	dev_info(&cp->pdev->dev, "_qcrypto_aead_decrypt_aes_cbc: %p\n", req);
@@ -1988,7 +2025,7 @@
 	struct qcrypto_cipher_req_ctx *rctx;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(areq);
 	rctx->aead = 1;
@@ -2012,7 +2049,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2032,7 +2069,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2057,7 +2094,7 @@
 	struct qcrypto_cipher_req_ctx *rctx;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(areq);
 	rctx->aead = 1;
@@ -2081,7 +2118,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2101,7 +2138,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2123,7 +2160,7 @@
 	struct qcrypto_cipher_req_ctx *rctx;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(areq);
 	rctx->aead = 1;
@@ -2146,7 +2183,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2166,7 +2203,7 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2188,7 +2225,7 @@
 	struct qcrypto_cipher_req_ctx *rctx;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	rctx = aead_request_ctx(areq);
 	rctx->aead = 1;
@@ -2220,10 +2257,9 @@
 static int _sha1_init(struct ahash_request *req)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-	struct crypto_priv *cp = sha_ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	_sha_init(sha_ctx);
 	sha_ctx->alg = QCE_HASH_SHA1;
@@ -2241,10 +2277,9 @@
 static int _sha256_init(struct ahash_request *req)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-	struct crypto_priv *cp = sha_ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 
 	_sha_init(sha_ctx);
 	sha_ctx->alg = QCE_HASH_SHA256;
@@ -2347,7 +2382,7 @@
 
 	srctx = ahash_request_ctx(req);
 	srctx->orig_src = req->src;
-	srctx->data = kzalloc((req->nbytes + 64), GFP_KERNEL);
+	srctx->data = kzalloc((req->nbytes + 64), GFP_ATOMIC);
 	if (srctx->data == NULL) {
 		pr_err("Mem Alloc fail rctx->data, err %ld for 0x%x\n",
 				PTR_ERR(srctx->data), (req->nbytes + 64));
@@ -2355,7 +2390,8 @@
 	}
 
 	num_sg = qcrypto_count_sg(req->src, req->nbytes);
-	bytes = sg_copy_to_buffer(req->src, num_sg, srctx->data, req->nbytes);
+	bytes = qcrypto_sg_copy_to_buffer(req->src, num_sg, srctx->data,
+						req->nbytes);
 	if (bytes != req->nbytes)
 		pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes,
 							req->nbytes);
@@ -2390,7 +2426,7 @@
 	if (total <= sha_block_size) {
 		k_src = &sha_ctx->trailing_buf[sha_ctx->trailing_buf_len];
 		num_sg = qcrypto_count_sg(req->src, len);
-		bytes = sg_copy_to_buffer(req->src, num_sg, k_src, len);
+		bytes = qcrypto_sg_copy_to_buffer(req->src, num_sg, k_src, len);
 
 		sha_ctx->trailing_buf_len = total;
 		if (sha_ctx->alg == QCE_HASH_SHA1)
@@ -2431,13 +2467,13 @@
 	if (sha_ctx->trailing_buf_len) {
 		if (cp->ce_support.aligned_only)  {
 			sha_ctx->sg = kzalloc(sizeof(struct scatterlist),
-								GFP_KERNEL);
+								GFP_ATOMIC);
 			if (sha_ctx->sg == NULL) {
 				pr_err("MemAlloc fail sha_ctx->sg, error %ld\n",
 						PTR_ERR(sha_ctx->sg));
 				return -ENOMEM;
 			}
-			rctx->data2 = kzalloc((req->nbytes + 64), GFP_KERNEL);
+			rctx->data2 = kzalloc((req->nbytes + 64), GFP_ATOMIC);
 			if (rctx->data2 == NULL) {
 				pr_err("Mem Alloc fail srctx->data2, err %ld\n",
 							PTR_ERR(rctx->data2));
@@ -2458,7 +2494,7 @@
 		} else {
 			sg_mark_end(sg_last);
 			sha_ctx->sg = kzalloc(2 * (sizeof(struct scatterlist)),
-								GFP_KERNEL);
+								GFP_ATOMIC);
 			if (sha_ctx->sg == NULL) {
 				pr_err("MEMalloc fail sha_ctx->sg, error %ld\n",
 							PTR_ERR(sha_ctx->sg));
@@ -2688,7 +2724,7 @@
 	struct crypto_stat *pstat;
 	int ret = 0;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 	pstat->sha1_hmac_digest++;
 
 	_sha_init(sha_ctx);
@@ -2715,7 +2751,7 @@
 	struct crypto_stat *pstat;
 	int ret = 0;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 	pstat->sha256_hmac_digest++;
 
 	_sha_init(sha_ctx);
@@ -2853,10 +2889,9 @@
 static int _sha1_hmac_digest(struct ahash_request *req)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-	struct crypto_priv *cp = sha_ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 	pstat->sha1_hmac_digest++;
 
 	_sha_init(sha_ctx);
@@ -2871,10 +2906,9 @@
 static int _sha256_hmac_digest(struct ahash_request *req)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-	struct crypto_priv *cp = sha_ctx->cp;
 	struct crypto_stat *pstat;
 
-	pstat = &_qcrypto_stat[cp->pdev->id];
+	pstat = &_qcrypto_stat;
 	pstat->sha256_hmac_digest++;
 
 	_sha_init(sha_ctx);
@@ -3327,12 +3361,6 @@
 	int i;
 	struct msm_ce_hw_support *platform_support;
 
-	if (pdev->id >= MAX_CRYPTO_DEVICE) {
-		pr_err("%s: device id %d  exceeds allowed %d\n",
-				__func__, pdev->id, MAX_CRYPTO_DEVICE);
-		return -ENOENT;
-	}
-
 	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
 	if (!cp) {
 		pr_err("qcrypto Memory allocation of q_alg FAIL, error %ld\n",
@@ -3572,7 +3600,7 @@
 	},
 };
 
-static int _debug_qcrypto[MAX_CRYPTO_DEVICE];
+static int _debug_qcrypto;
 
 static int _debug_stats_open(struct inode *inode, struct file *file)
 {
@@ -3599,9 +3627,7 @@
 			size_t count, loff_t *ppos)
 {
 
-	int qcrypto = *((int *) file->private_data);
-
-	memset((char *)&_qcrypto_stat[qcrypto], 0, sizeof(struct crypto_stat));
+	memset((char *)&_qcrypto_stat, 0, sizeof(struct crypto_stat));
 	return count;
 };
 
@@ -3615,7 +3641,6 @@
 {
 	int rc;
 	char name[DEBUG_MAX_FNAME];
-	int i;
 	struct dentry *dent;
 
 	_debug_dent = debugfs_create_dir("qcrypto", NULL);
@@ -3625,17 +3650,15 @@
 		return PTR_ERR(_debug_dent);
 	}
 
-	for (i = 0; i < MAX_CRYPTO_DEVICE; i++) {
-		snprintf(name, DEBUG_MAX_FNAME-1, "stats-%d", i+1);
-		_debug_qcrypto[i] = i;
-		dent = debugfs_create_file(name, 0644, _debug_dent,
-				&_debug_qcrypto[i], &_debug_stats_ops);
-		if (dent == NULL) {
-			pr_err("qcrypto debugfs_create_file fail, error %ld\n",
-					PTR_ERR(dent));
-			rc = PTR_ERR(dent);
-			goto err;
-		}
+	snprintf(name, DEBUG_MAX_FNAME-1, "stats-%d", 1);
+	_debug_qcrypto = 0;
+	dent = debugfs_create_file(name, 0644, _debug_dent,
+				&_debug_qcrypto, &_debug_stats_ops);
+	if (dent == NULL) {
+		pr_err("qcrypto debugfs_create_file fail, error %ld\n",
+				PTR_ERR(dent));
+		rc = PTR_ERR(dent);
+		goto err;
 	}
 	return 0;
 err:
diff --git a/drivers/gpu/ion/msm/ion_iommu_map.c b/drivers/gpu/ion/msm/ion_iommu_map.c
index 5ce03db..0a4fe1f 100644
--- a/drivers/gpu/ion/msm/ion_iommu_map.c
+++ b/drivers/gpu/ion/msm/ion_iommu_map.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/dma-buf.h>
 #include <linux/export.h>
 #include <linux/iommu.h>
 #include <linux/ion.h>
@@ -69,6 +70,7 @@
 	struct sg_table *table;
 	unsigned long size;
 	struct mutex lock;
+	struct dma_buf *dbuf;
 };
 
 static struct rb_root iommu_root;
@@ -85,9 +87,9 @@
 		parent = *p;
 		entry = rb_entry(parent, struct ion_iommu_meta, node);
 
-		if (meta->handle < entry->handle) {
+		if (meta->table < entry->table) {
 			p = &(*p)->rb_left;
-		} else if (meta->handle > entry->handle) {
+		} else if (meta->table > entry->table) {
 			p = &(*p)->rb_right;
 		} else {
 			pr_err("%s: handle %p already exists\n", __func__,
@@ -101,7 +103,7 @@
 }
 
 
-static struct ion_iommu_meta *ion_iommu_meta_lookup(struct ion_handle *handle)
+static struct ion_iommu_meta *ion_iommu_meta_lookup(struct sg_table *table)
 {
 	struct rb_root *root = &iommu_root;
 	struct rb_node **p = &root->rb_node;
@@ -112,9 +114,9 @@
 		parent = *p;
 		entry = rb_entry(parent, struct ion_iommu_meta, node);
 
-		if (handle < entry->handle)
+		if (table < entry->table)
 			p = &(*p)->rb_left;
-		else if (handle > entry->handle)
+		else if (table > entry->table)
 			p = &(*p)->rb_right;
 		else
 			return entry;
@@ -319,7 +321,8 @@
 	return ERR_PTR(ret);
 }
 
-static struct ion_iommu_meta *ion_iommu_meta_create(struct ion_handle *handle,
+static struct ion_iommu_meta *ion_iommu_meta_create(struct ion_client *client,
+						struct ion_handle *handle,
 						struct sg_table *table,
 						unsigned long size)
 {
@@ -333,6 +336,7 @@
 	meta->handle = handle;
 	meta->table = table;
 	meta->size = size;
+	meta->dbuf = ion_share_dma_buf(client, handle);
 	kref_init(&meta->ref);
 	mutex_init(&meta->lock);
 	ion_iommu_meta_add(meta);
@@ -347,6 +351,7 @@
 
 
 	rb_erase(&meta->node, &iommu_root);
+	dma_buf_put(meta->dbuf);
 	kfree(meta);
 }
 
@@ -427,13 +432,13 @@
 	}
 
 	mutex_lock(&msm_iommu_map_mutex);
-	iommu_meta = ion_iommu_meta_lookup(handle);
+	iommu_meta = ion_iommu_meta_lookup(table);
 
 	if (!iommu_meta)
-		iommu_meta = ion_iommu_meta_create(handle, table, size);
+		iommu_meta = ion_iommu_meta_create(client, handle, table, size);
 	else
 		kref_get(&iommu_meta->ref);
-
+	BUG_ON(iommu_meta->size != size);
 	mutex_unlock(&msm_iommu_map_mutex);
 
 	iommu_map = ion_iommu_lookup(iommu_meta, domain_num, partition_num);
@@ -493,6 +498,7 @@
 {
 	struct ion_iommu_map *iommu_map;
 	struct ion_iommu_meta *meta;
+	struct sg_table *table;
 
 	if (IS_ERR_OR_NULL(client)) {
 		pr_err("%s: client pointer is invalid\n", __func__);
@@ -503,13 +509,14 @@
 		return;
 	}
 
+	table = ion_sg_table(client, handle);
 
 	mutex_lock(&msm_iommu_map_mutex);
-	meta = ion_iommu_meta_lookup(handle);
+	meta = ion_iommu_meta_lookup(table);
 	if (!meta) {
 		WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
 				domain_num, partition_num, handle);
-		mutex_lock(&msm_iommu_map_mutex);
+		mutex_unlock(&msm_iommu_map_mutex);
 		goto out;
 
 	}
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 60e457d..7cd9943 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1864,6 +1864,9 @@
 	if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
 		entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
 
+	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU)
+		entry->memdesc.priv |= KGSL_MEMDESC_GUARD_PAGE;
+
 	switch (memtype) {
 	case KGSL_USER_MEM_TYPE_PMEM:
 		if (param->fd == 0 || param->len == 0)
@@ -2088,6 +2091,9 @@
 	if (entry == NULL)
 		return -ENOMEM;
 
+	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU)
+		entry->memdesc.priv |= KGSL_MEMDESC_GUARD_PAGE;
+
 	result = kgsl_allocate_user(&entry->memdesc, private->pagetable, size,
 				    flags);
 	if (result != 0)
@@ -2841,10 +2847,6 @@
 		int sglen = entry->memdesc.sglen;
 		unsigned long addr = vma->vm_start;
 
-		/* don't map in the guard page, it should always fault */
-		if (kgsl_memdesc_has_guard_page(&entry->memdesc))
-			sglen--;
-
 		for_each_sg(entry->memdesc.sg, s, sglen, i) {
 			int j;
 			for (j = 0; j < (sg_dma_len(s) >> PAGE_SHIFT); j++) {
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 8d071d1..6f139b9 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -615,7 +615,7 @@
 {
 	unsigned int numpages;
 	unsigned int pte, ptefirst, ptelast, superpte;
-	unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
+	unsigned int range = memdesc->size;
 	struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
 
 	/* All GPU addresses as assigned are page aligned, but some
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 206f4ef..3057723 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -84,6 +84,13 @@
 
 struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
 
+/*
+ * One page allocation for a guard region to protect against over-zealous
+ * GPU pre-fetch
+ */
+
+static struct page *kgsl_guard_page;
+
 static int get_iommu_unit(struct device *dev, struct kgsl_mmu **mmu_out,
 			struct kgsl_iommu_unit **iommu_unit_out)
 {
@@ -1378,6 +1385,15 @@
 		iommu_ops.mmu_cleanup_pt = kgsl_iommu_cleanup_regs;
 	}
 
+	if (kgsl_guard_page == NULL) {
+		kgsl_guard_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
+				__GFP_HIGHMEM);
+		if (kgsl_guard_page == NULL) {
+			status = -ENOMEM;
+			goto done;
+		}
+	}
+
 	dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
 			__func__);
 done:
@@ -1628,7 +1644,7 @@
 		unsigned int *tlb_flags)
 {
 	int ret;
-	unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
+	unsigned int range = memdesc->size;
 	struct kgsl_iommu_pt *iommu_pt = pt->priv;
 
 	/* All GPU addresses as assigned are page aligned, but some
@@ -1640,6 +1656,9 @@
 	if (range == 0 || gpuaddr == 0)
 		return 0;
 
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		range += PAGE_SIZE;
+
 	ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range);
 	if (ret)
 		KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed "
@@ -1664,14 +1683,10 @@
 	int ret;
 	unsigned int iommu_virt_addr;
 	struct kgsl_iommu_pt *iommu_pt = pt->priv;
-	int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
+	int size = memdesc->size;
 
 	BUG_ON(NULL == iommu_pt);
 
-	/* if there's a guard page, we'll map it read only below */
-	if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc))
-			size -= PAGE_SIZE;
-
 	iommu_virt_addr = memdesc->gpuaddr;
 
 	ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg,
@@ -1682,16 +1697,14 @@
 			protflags, ret);
 		return ret;
 	}
-	if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc)) {
-		struct scatterlist *sg = &memdesc->sg[memdesc->sglen - 1];
-
+	if (kgsl_memdesc_has_guard_page(memdesc)) {
 		ret = iommu_map(iommu_pt->domain, iommu_virt_addr + size,
-				kgsl_get_sg_pa(sg), PAGE_SIZE,
+				page_to_phys(kgsl_guard_page), PAGE_SIZE,
 				protflags & ~IOMMU_WRITE);
 		if (ret) {
-			KGSL_CORE_ERR("iommu_map(%p, %x, %x, %x) err: %d\n",
+			KGSL_CORE_ERR("iommu_map(%p, %x, guard, %x) err: %d\n",
 				iommu_pt->domain, iommu_virt_addr + size,
-				kgsl_get_sg_pa(sg), protflags & ~IOMMU_WRITE,
+				protflags & ~IOMMU_WRITE,
 				ret);
 			/* cleanup the partial mapping */
 			iommu_unmap_range(iommu_pt->domain, iommu_virt_addr,
@@ -1771,6 +1784,11 @@
 
 	kfree(iommu);
 
+	if (kgsl_guard_page != NULL) {
+		__free_page(kgsl_guard_page);
+		kgsl_guard_page = NULL;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 6e41707..3ebfdcd 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -640,7 +640,10 @@
 		}
 	}
 
-	size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
+	/* Add space for the guard page when allocating the mmu VA. */
+	size = memdesc->size;
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		size += PAGE_SIZE;
 
 	pool = pagetable->pool;
 
@@ -738,7 +741,10 @@
 		return 0;
 	}
 
-	size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
+	/* Add space for the guard page when freeing the mmu VA. */
+	size = memdesc->size;
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		size += PAGE_SIZE;
 
 	start_addr = memdesc->gpuaddr;
 	end_addr = (memdesc->gpuaddr + size);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 62db513..b9bc432 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -65,14 +65,6 @@
 		mem_entry_max_show), \
 }
 
-
-/*
- * One page allocation for a guard region to protect against over-zealous
- * GPU pre-fetch
- */
-
-static struct page *kgsl_guard_page;
-
 /**
  * Given a kobj, find the process structure attached to it
  */
@@ -364,10 +356,6 @@
 	struct scatterlist *sg;
 	int sglen = memdesc->sglen;
 
-	/* Don't free the guard page if it was used */
-	if (memdesc->priv & KGSL_MEMDESC_GUARD_PAGE)
-		sglen--;
-
 	kgsl_driver.stats.page_alloc -= memdesc->size;
 
 	if (memdesc->hostptr) {
@@ -402,10 +390,6 @@
 		int sglen = memdesc->sglen;
 		int i, count = 0;
 
-		/* Don't map the guard page if it exists */
-		if (memdesc->priv & KGSL_MEMDESC_GUARD_PAGE)
-			sglen--;
-
 		/* create a list of pages to call vmap */
 		pages = vmalloc(npages * sizeof(struct page *));
 		if (!pages) {
@@ -564,14 +548,6 @@
 
 	sglen_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT;
 
-	/*
-	 * Add guard page to the end of the allocation when the
-	 * IOMMU is in use.
-	 */
-
-	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU)
-		sglen_alloc++;
-
 	memdesc->size = size;
 	memdesc->pagetable = pagetable;
 	memdesc->ops = &kgsl_page_alloc_ops;
@@ -647,26 +623,6 @@
 		len -= page_size;
 	}
 
-	/* Add the guard page to the end of the sglist */
-
-	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) {
-		/*
-		 * It doesn't matter if we use GFP_ZERO here, this never
-		 * gets mapped, and we only allocate it once in the life
-		 * of the system
-		 */
-
-		if (kgsl_guard_page == NULL)
-			kgsl_guard_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
-				__GFP_HIGHMEM);
-
-		if (kgsl_guard_page != NULL) {
-			sg_set_page(&memdesc->sg[sglen++], kgsl_guard_page,
-				PAGE_SIZE, 0);
-			memdesc->priv |= KGSL_MEMDESC_GUARD_PAGE;
-		}
-	}
-
 	memdesc->sglen = sglen;
 
 	/*
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 279490f..14ae0dc 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -295,15 +295,4 @@
 	return ret;
 }
 
-static inline int kgsl_sg_size(struct scatterlist *sg, int sglen)
-{
-	int i, size = 0;
-	struct scatterlist *s;
-
-	for_each_sg(sg, s, sglen, i) {
-		size += s->length;
-	}
-
-	return size;
-}
 #endif /* __KGSL_SHAREDMEM_H */
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 986c062..dbe378c 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/firmware.h>
+#include <linux/string.h>
 #include <linux/input/synaptics_dsx.h>
 #include "synaptics_i2c_rmi4.h"
 
@@ -34,14 +35,7 @@
 #define FORCE_UPDATE false
 #define INSIDE_FIRMWARE_UPDATE
 
-#define CHECKSUM_OFFSET 0x00
-#define BOOTLOADER_VERSION_OFFSET 0x07
-#define IMAGE_SIZE_OFFSET 0x08
-#define CONFIG_SIZE_OFFSET 0x0C
-#define PRODUCT_ID_OFFSET 0x10
-#define PRODUCT_INFO_OFFSET 0x1E
 #define FW_IMAGE_OFFSET 0x100
-#define PRODUCT_ID_SIZE 10
 
 #define BOOTLOADER_ID_OFFSET 0
 #define FLASH_PROPERTIES_OFFSET 2
@@ -59,10 +53,14 @@
 #define BLOCK_NUMBER_OFFSET 0
 #define BLOCK_DATA_OFFSET 2
 
-#define UI_CONFIG_AREA 0x00
-#define PERM_CONFIG_AREA 0x01
-#define BL_CONFIG_AREA 0x02
-#define DISP_CONFIG_AREA 0x03
+#define NAME_BUFFER_SIZE 128
+
+enum falsh_config_area {
+	UI_CONFIG_AREA = 0x00,
+	PERM_CONFIG_AREA = 0x01,
+	BL_CONFIG_AREA = 0x02,
+	DISP_CONFIG_AREA = 0x03
+};
 
 enum flash_command {
 	CMD_WRITE_FW_BLOCK		= 0x2,
@@ -70,9 +68,10 @@
 	CMD_READ_CONFIG_BLOCK	= 0x5,
 	CMD_WRITE_CONFIG_BLOCK	= 0x6,
 	CMD_ERASE_CONFIG		= 0x7,
+	CMD_READ_SENSOR_ID		= 0x8,
 	CMD_ERASE_BL_CONFIG		= 0x9,
 	CMD_ERASE_DISP_CONFIG	= 0xA,
-	CMD_ENABLE_FLASH_PROG	= 0xF,
+	CMD_ENABLE_FLASH_PROG	= 0xF
 };
 
 enum flash_area {
@@ -81,6 +80,11 @@
 	CONFIG_AREA
 };
 
+enum image_file_option {
+	OPTION_BUILD_INFO = 0,
+	OPTION_CONTAIN_BOOTLOADER = 1,
+};
+
 #define SLEEP_MODE_NORMAL (0x00)
 #define SLEEP_MODE_SENSOR_SLEEP (0x01)
 #define SLEEP_MODE_RESERVED0 (0x02)
@@ -91,6 +95,8 @@
 #define ERASE_WAIT_MS (5 * 1000)
 #define RESET_WAIT_MS (500)
 
+#define POLLING_MODE 0
+
 #define SLEEP_TIME_US 50
 
 static ssize_t fwu_sysfs_show_image(struct file *data_file,
@@ -139,6 +145,40 @@
 
 static int fwu_wait_for_idle(int timeout_ms);
 
+struct image_header_data {
+	union {
+		struct {
+			/* 0x00-0x0F */
+			unsigned char file_checksum[4];
+			unsigned char reserved_04;
+			unsigned char reserved_05;
+			unsigned char options_firmware_id:1;
+			unsigned char options_contain_bootloader:1;
+			unsigned char options_reserved:6;
+			unsigned char bootloader_version;
+			unsigned char firmware_size[4];
+			unsigned char config_size[4];
+			/* 0x10-0x1F */
+			unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE];
+			unsigned char reserved_1a;
+			unsigned char reserved_1b;
+			unsigned char reserved_1c;
+			unsigned char reserved_1d;
+			unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+			/* 0x20-0x2F */
+			unsigned char reserved_20_2f[0x10];
+			/* 0x30-0x3F */
+			unsigned char ds_firmware_id[0x10];
+			/* 0x40-0x4F */
+			unsigned char ds_customize_info[10];
+			unsigned char reserved_4a_4f[6];
+			/* 0x50-0x53*/
+			unsigned char firmware_id[4];
+		} __packed;
+		unsigned char data[54];
+	};
+};
+
 struct image_header {
 	unsigned int checksum;
 	unsigned int image_size;
@@ -147,6 +187,8 @@
 	unsigned char bootloader_version;
 	unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
 	unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+	unsigned int firmware_id;
+	bool is_contain_build_info;
 };
 
 struct pdt_properties {
@@ -245,6 +287,7 @@
 	struct f34_flash_properties flash_properties;
 	struct workqueue_struct *fwu_workqueue;
 	struct delayed_work fwu_work;
+	char *firmware_name;
 };
 
 static struct bin_attribute dev_attr_data = {
@@ -308,18 +351,36 @@
 			(unsigned int)ptr[3] * 0x1000000;
 }
 
+static unsigned int extract_uint_be(const unsigned char *ptr)
+{
+	return (unsigned int)ptr[3] +
+			(unsigned int)ptr[2] * 0x100 +
+			(unsigned int)ptr[1] * 0x10000 +
+			(unsigned int)ptr[0] * 0x1000000;
+}
+
 static void parse_header(struct image_header *header,
 		const unsigned char *fw_image)
 {
-	header->checksum = extract_uint(&fw_image[CHECKSUM_OFFSET]);
-	header->bootloader_version = fw_image[BOOTLOADER_VERSION_OFFSET];
-	header->image_size = extract_uint(&fw_image[IMAGE_SIZE_OFFSET]);
-	header->config_size = extract_uint(&fw_image[CONFIG_SIZE_OFFSET]);
-	memcpy(header->product_id, &fw_image[PRODUCT_ID_OFFSET],
-			SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
-	header->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
-	memcpy(header->product_info, &fw_image[PRODUCT_INFO_OFFSET],
-			SYNAPTICS_RMI4_PRODUCT_INFO_SIZE);
+	struct image_header_data *data = (struct image_header_data *)fw_image;
+	header->checksum = extract_uint(data->file_checksum);
+	header->bootloader_version = data->bootloader_version;
+	header->image_size = extract_uint(data->firmware_size);
+	header->config_size = extract_uint(data->config_size);
+	memcpy(header->product_id, data->product_id,
+		sizeof(data->product_id));
+	header->product_id[sizeof(data->product_info)] = 0;
+	memcpy(header->product_info, data->product_info,
+		sizeof(data->product_info));
+
+	header->is_contain_build_info =
+		(data->options_firmware_id == (1 << OPTION_BUILD_INFO));
+	if (header->is_contain_build_info) {
+		header->firmware_id = extract_uint(data->firmware_id);
+		dev_info(&fwu->rmi4_data->i2c_client->dev,
+			"%s Firwmare build id %d\n", __func__,
+			header->firmware_id);
+	}
 
 #ifdef DEBUG_FW_UPDATE
 	dev_info(&fwu->rmi4_data->i2c_client->dev,
@@ -516,6 +577,9 @@
 	int count = 0;
 	int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
 	do {
+		#if POLLING_MODE
+		fwu_read_f34_flash_status();
+		#endif
 		if (fwu->flash_control.command == 0x00)
 			return 0;
 
@@ -533,7 +597,7 @@
 	return -ETIMEDOUT;
 }
 
-static enum flash_area fwu_go_nogo(void)
+static enum flash_area fwu_go_nogo(struct image_header *header)
 {
 	int retval = 0;
 	int index = 0;
@@ -569,7 +633,6 @@
 		goto exit;
 	}
 
-
 	/* device firmware id */
 	retval = fwu->fn_ptr->read(fwu->rmi4_data,
 				fwu->f01_fd.query_base_addr + 18,
@@ -577,37 +640,45 @@
 				sizeof(firmware_id));
 	if (retval < 0) {
 		dev_err(&i2c_client->dev,
-			"Failed to read firmware ID (code %d).\n", retval);
+			"%s: Failed to read firmware ID (code %d).\n",
+			__func__, retval);
 		goto exit;
 	}
 	firmware_id[3] = 0;
 	deviceFirmwareID = extract_uint(firmware_id);
 
 	/* .img firmware id */
-	strptr = strnstr(fwu->rmi4_data->fw_image_name, "PR",
-			sizeof(fwu->rmi4_data->fw_image_name));
-	if (!strptr) {
+	if (header->is_contain_build_info) {
 		dev_err(&i2c_client->dev,
-			"No valid PR number (PRxxxxxxx)" \
-			"found in image file name...\n");
-		goto exit;
+			"%s: Image option contains build info.\n",
+			__func__);
+		imageFirmwareID = header->firmware_id;
+	} else {
+		strptr = strnstr(fwu->firmware_name, "PR",
+				sizeof(fwu->firmware_name));
+		if (!strptr) {
+			dev_err(&i2c_client->dev,
+				"No valid PR number (PRxxxxxxx)" \
+				"found in image file name...\n");
+			goto exit;
+		}
+
+		strptr += 2;
+		while (strptr[index] >= '0' && strptr[index] <= '9') {
+			imagePR[index] = strptr[index];
+			index++;
+		}
+		imagePR[index] = 0;
+
+		retval = kstrtoul(imagePR, 10, &imageFirmwareID);
+		if (retval ==  -EINVAL) {
+			dev_err(&i2c_client->dev,
+				"invalid image firmware id...\n");
+			goto exit;
+		}
 	}
 
-	strptr += 2;
-	while (strptr[index] >= '0' && strptr[index] <= '9') {
-		imagePR[index] = strptr[index];
-		index++;
-	}
-	imagePR[index] = 0;
-
-	retval = kstrtoul(imagePR, 10, &imageFirmwareID);
-	if (retval ==  -EINVAL) {
-		dev_err(&i2c_client->dev,
-			"invalid image firmware id...\n");
-		goto exit;
-	}
-
-	dev_info(&i2c_client->dev,
+	dev_dbg(&i2c_client->dev,
 			"Device firmware id %d, .img firmware id %d\n",
 			deviceFirmwareID,
 			(unsigned int)imageFirmwareID);
@@ -617,7 +688,8 @@
 	} else if (imageFirmwareID < deviceFirmwareID) {
 		flash_area = NONE;
 		dev_info(&i2c_client->dev,
-			"Img fw is older than device fw.  Skip fw update.\n");
+			"%s: Img fw is older than device fw. Skip fw update.\n",
+			__func__);
 		goto exit;
 	}
 
@@ -628,24 +700,29 @@
 				sizeof(config_id));
 	if (retval < 0) {
 		dev_err(&i2c_client->dev,
-			"Failed to read config ID (code %d).\n", retval);
+			"%s: Failed to read config ID (code %d).\n",
+			__func__, retval);
 		flash_area = NONE;
 		goto exit;
 	}
-	deviceConfigID =  extract_uint(config_id);
+	deviceConfigID =  extract_uint_be(config_id);
 
-	dev_info(&i2c_client->dev,
+	dev_dbg(&i2c_client->dev,
 		"Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
 		config_id[0], config_id[1], config_id[2], config_id[3]);
 
 	/* .img config id */
-	dev_info(&i2c_client->dev,
+	dev_dbg(&i2c_client->dev,
 			".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
 			fwu->config_data[0],
 			fwu->config_data[1],
 			fwu->config_data[2],
 			fwu->config_data[3]);
-	imageConfigID =  extract_uint(fwu->config_data);
+	imageConfigID =  extract_uint_be(fwu->config_data);
+
+	dev_dbg(&i2c_client->dev,
+		"%s: Device config ID %d, .img config ID %d\n",
+		__func__, deviceConfigID, imageConfigID);
 
 	if (imageConfigID > deviceConfigID) {
 		flash_area = CONFIG_AREA;
@@ -656,10 +733,10 @@
 	kfree(imagePR);
 	if (flash_area == NONE)
 		dev_info(&i2c_client->dev,
-			"Nothing needs to be updated\n");
+			"%s: Nothing needs to be updated\n", __func__);
 	else
 		dev_info(&i2c_client->dev,
-			"Update %s block\n",
+			"%s: Update %s block\n", __func__,
 			flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG");
 	return flash_area;
 }
@@ -1210,7 +1287,7 @@
 
 static int fwu_start_reflash(void)
 {
-	int retval;
+	int retval = 0;
 	struct image_header header;
 	const unsigned char *fw_image;
 	const struct firmware *fw_entry = NULL;
@@ -1229,18 +1306,30 @@
 	if (fwu->ext_data_source)
 		fw_image = fwu->ext_data_source;
 	else {
-		dev_dbg(&fwu->rmi4_data->i2c_client->dev,
-				"%s: Requesting firmware image %s\n",
-				__func__, fwu->rmi4_data->fw_image_name);
+		fwu->firmware_name = kcalloc(NAME_BUFFER_SIZE,
+			sizeof(char), GFP_KERNEL);
+		if (!fwu->firmware_name) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s Failed to allocate firmware name (%d).\n",
+				__func__, NAME_BUFFER_SIZE);
+			retval = -ENOMEM;
+			goto memory_exit;
+		}
+
+		snprintf(fwu->firmware_name, NAME_BUFFER_SIZE, "%s",
+			fwu->rmi4_data->fw_image_name);
+		dev_info(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Requesting firmware image %s\n",
+			__func__, fwu->firmware_name);
 
 		retval = request_firmware(&fw_entry,
-				fwu->rmi4_data->fw_image_name,
+				fwu->firmware_name,
 				&fwu->rmi4_data->i2c_client->dev);
 		if (retval != 0) {
 			dev_err(&fwu->rmi4_data->i2c_client->dev,
 					"%s: Firmware image %s not available\n",
 					__func__,
-					fwu->rmi4_data->fw_image_name);
+					fwu->firmware_name);
 			retval = -EINVAL;
 			goto exit;
 		}
@@ -1264,7 +1353,7 @@
 	if (fwu->ext_data_source)
 		flash_area = UI_FIRMWARE;
 	else
-		flash_area = fwu_go_nogo();
+		flash_area = fwu_go_nogo(&header);
 
 	switch (flash_area) {
 	case NONE:
@@ -1318,6 +1407,8 @@
 
 	pr_notice("%s: End of reflash process\n", __func__);
 exit:
+	kfree(fwu->firmware_name);
+memory_exit:
 	return retval;
 }
 
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 16b1f8f..681822a 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -24,7 +24,7 @@
 #define SYNAPTICS_DS4 (1 << 0)
 #define SYNAPTICS_DS5 (1 << 1)
 #define SYNAPTICS_DSX_DRIVER_PRODUCT SYNAPTICS_DS4
-#define SYNAPTICS_DSX_DRIVER_VERSION 0x1004
+#define SYNAPTICS_DSX_DRIVER_VERSION 0x1005
 
 #include <linux/version.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 962c079..a95eda7 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -94,7 +94,8 @@
 
 	for (i = 0; i < ispif->vfe_info.num_vfe; i++) {
 
-		msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_CTRL_0(i));
+		msm_camera_io_w(1 << PIX0_LINE_BUF_EN_BIT,
+			ispif->base + ISPIF_VFE_m_CTRL_0(i));
 		msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(i));
 		msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(i));
 		msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(i));
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
index 76aa695..ac697fb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
@@ -40,7 +40,7 @@
 	struct msm_flash_fn_t *func_tbl;
 	const char *led_trigger_name[MAX_LED_TRIGGERS];
 	struct led_trigger *led_trigger[MAX_LED_TRIGGERS];
-	uint32_t max_current[MAX_LED_TRIGGERS];
+	uint32_t op_current[MAX_LED_TRIGGERS];
 	void *data;
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
index 1a75a5a..c6f1f72 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -59,11 +59,11 @@
 
 	case MSM_CAMERA_LED_LOW:
 		led_trigger_event(fctrl->led_trigger[0],
-			fctrl->max_current[0] / 2);
+			fctrl->op_current[0] / 2);
 		break;
 
 	case MSM_CAMERA_LED_HIGH:
-		led_trigger_event(fctrl->led_trigger[0], fctrl->max_current[0]);
+		led_trigger_event(fctrl->led_trigger[0], fctrl->op_current[0]);
 		break;
 
 	case MSM_CAMERA_LED_INIT:
@@ -144,7 +144,7 @@
 			CDBG("default trigger %s\n", fctrl.led_trigger_name[i]);
 
 			rc = of_property_read_u32(flash_src_node,
-				"qcom,max-current", &fctrl.max_current[i]);
+				"qcom,current", &fctrl.op_current[i]);
 			if (rc < 0) {
 				pr_err("failed rc %d\n", rc);
 				of_node_put(flash_src_node);
@@ -153,7 +153,7 @@
 
 			of_node_put(flash_src_node);
 
-			CDBG("max_current[%d] %d\n", i, fctrl.max_current[i]);
+			CDBG("max_current[%d] %d\n", i, fctrl.op_current[i]);
 
 			led_trigger_register_simple(fctrl.led_trigger_name[i],
 				&fctrl.led_trigger[i]);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index feb239e..eb5a03c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -729,6 +729,8 @@
 			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
 			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
+		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
+			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
 		switch (fill_buf_done->picture_type) {
 		case HAL_PICTURE_IDR:
 		case HAL_PICTURE_I:
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 153552d..d673713 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -3790,6 +3790,27 @@
 		if (retval < 0)
 			FMDERR("set CF0 Threshold failed\n");
 		break;
+	case V4L2_CID_PRIVATE_RXREPEATCOUNT:
+		rd.mode = RDS_PS0_XFR_MODE;
+		rd.length = RDS_PS0_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed for PS0 %x", retval);
+			return retval;
+		}
+		wrd.mode = RDS_PS0_XFR_MODE;
+		wrd.length = RDS_PS0_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[RX_REPEATE_BYTE_OFFSET] = ctrl->value;
+
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set RxRePeat count failed\n");
+		break;
 	default:
 		retval = -EINVAL;
 	}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2573a16..a7932ba 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -51,10 +51,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad525x_dpot-spi.
 
-config ANDROID_PMEM
-	bool "Android pmem allocator"
-	default y
-
 config ATMEL_PWM
 	tristate "Atmel AT32/AT91 PWM support"
 	depends on HAVE_CLK
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 327d1ec..760f768 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -19,7 +19,6 @@
 obj-$(CONFIG_SENSORS_BH1780)	+= bh1780gli.o
 obj-$(CONFIG_SENSORS_BH1770)	+= bh1770glc.o
 obj-$(CONFIG_SENSORS_APDS990X)	+= apds990x.o
-obj-$(CONFIG_ANDROID_PMEM)	+= pmem.o
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
deleted file mode 100644
index e91db7a..0000000
--- a/drivers/misc/pmem.c
+++ /dev/null
@@ -1,2961 +0,0 @@
-/* drivers/android/pmem.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/export.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/fmem.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/debugfs.h>
-#include <linux/android_pmem.h>
-#include <linux/mempolicy.h>
-#include <linux/sched.h>
-#include <linux/kobject.h>
-#include <linux/pm_runtime.h>
-#include <linux/memory_alloc.h>
-#include <linux/vmalloc.h>
-#include <linux/io.h>
-#include <linux/mm_types.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/cacheflush.h>
-#include <asm/sizes.h>
-#include <asm/mach/map.h>
-#include <asm/page.h>
-
-#define PMEM_MAX_DEVICES (10)
-
-#define PMEM_MAX_ORDER (128)
-#define PMEM_MIN_ALLOC PAGE_SIZE
-
-#define PMEM_INITIAL_NUM_BITMAP_ALLOCATIONS (64)
-
-#define PMEM_32BIT_WORD_ORDER (5)
-#define PMEM_BITS_PER_WORD_MASK (BITS_PER_LONG - 1)
-
-#ifdef CONFIG_ANDROID_PMEM_DEBUG
-#define PMEM_DEBUG 1
-#else
-#define PMEM_DEBUG 0
-#endif
-
-#define SYSTEM_ALLOC_RETRY 10
-
-/* indicates that a refernce to this file has been taken via get_pmem_file,
- * the file should not be released until put_pmem_file is called */
-#define PMEM_FLAGS_BUSY 0x1
-/* indicates that this is a suballocation of a larger master range */
-#define PMEM_FLAGS_CONNECTED 0x1 << 1
-/* indicates this is a master and not a sub allocation and that it is mmaped */
-#define PMEM_FLAGS_MASTERMAP 0x1 << 2
-/* submap and unsubmap flags indicate:
- * 00: subregion has never been mmaped
- * 10: subregion has been mmaped, reference to the mm was taken
- * 11: subretion has ben released, refernece to the mm still held
- * 01: subretion has been released, reference to the mm has been released
- */
-#define PMEM_FLAGS_SUBMAP 0x1 << 3
-#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
-
-struct pmem_data {
-	/* in alloc mode: an index into the bitmap
-	 * in no_alloc mode: the size of the allocation */
-	int index;
-	/* see flags above for descriptions */
-	unsigned int flags;
-	/* protects this data field, if the mm_mmap sem will be held at the
-	 * same time as this sem, the mm sem must be taken first (as this is
-	 * the order for vma_open and vma_close ops */
-	struct rw_semaphore sem;
-	/* info about the mmaping process */
-	struct vm_area_struct *vma;
-	/* task struct of the mapping process */
-	struct task_struct *task;
-	/* process id of teh mapping process */
-	pid_t pid;
-	/* file descriptor of the master */
-	int master_fd;
-	/* file struct of the master */
-	struct file *master_file;
-	/* a list of currently available regions if this is a suballocation */
-	struct list_head region_list;
-	/* a linked list of data so we can access them for debugging */
-	struct list_head list;
-#if PMEM_DEBUG
-	int ref;
-#endif
-};
-
-struct pmem_bits {
-	unsigned allocated:1;		/* 1 if allocated, 0 if free */
-	unsigned order:7;		/* size of the region in pmem space */
-};
-
-struct pmem_region_node {
-	struct pmem_region region;
-	struct list_head list;
-};
-
-#define PMEM_DEBUG_MSGS 0
-#if PMEM_DEBUG_MSGS
-#define DLOG(fmt,args...) \
-	do { pr_debug("[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
-		    ##args); } \
-	while (0)
-#else
-#define DLOG(x...) do {} while (0)
-#endif
-
-enum pmem_align {
-	PMEM_ALIGN_4K,
-	PMEM_ALIGN_1M,
-};
-
-#define PMEM_NAME_SIZE 16
-
-struct alloc_list {
-	void *addr;                  /* physical addr of allocation */
-	void *aaddr;                 /* aligned physical addr       */
-	unsigned int size;           /* total size of allocation    */
-	unsigned char __iomem *vaddr; /* Virtual addr                */
-	struct list_head allocs;
-};
-
-struct pmem_info {
-	struct miscdevice dev;
-	/* physical start address of the remaped pmem space */
-	unsigned long base;
-	/* vitual start address of the remaped pmem space */
-	unsigned char __iomem *vbase;
-	/* total size of the pmem space */
-	unsigned long size;
-	/* number of entries in the pmem space */
-	unsigned long num_entries;
-	/* pfn of the garbage page in memory */
-	unsigned long garbage_pfn;
-	/* which memory type (i.e. SMI, EBI1) this PMEM device is backed by */
-	unsigned memory_type;
-
-	char name[PMEM_NAME_SIZE];
-
-	/* index of the garbage page in the pmem space */
-	int garbage_index;
-	/* reserved virtual address range */
-	struct vm_struct *area;
-
-	enum pmem_allocator_type allocator_type;
-
-	int (*allocate)(const int,
-			const unsigned long,
-			const unsigned int);
-	int (*free)(int, int);
-	int (*free_space)(int, struct pmem_freespace *);
-	unsigned long (*len)(int, struct pmem_data *);
-	unsigned long (*start_addr)(int, struct pmem_data *);
-
-	/* actual size of memory element, e.g.: (4 << 10) is 4K */
-	unsigned int quantum;
-
-	/* indicates maps of this region should be cached, if a mix of
-	 * cached and uncached is desired, set this and open the device with
-	 * O_SYNC to get an uncached region */
-	unsigned cached;
-	unsigned buffered;
-	union {
-		struct {
-			/* in all_or_nothing allocator mode the first mapper
-			 * gets the whole space and sets this flag */
-			unsigned allocated;
-		} all_or_nothing;
-
-		struct {
-			/* the buddy allocator bitmap for the region
-			 * indicating which entries are allocated and which
-			 * are free.
-			 */
-
-			struct pmem_bits *buddy_bitmap;
-		} buddy_bestfit;
-
-		struct {
-			unsigned int bitmap_free; /* # of zero bits/quanta */
-			uint32_t *bitmap;
-			int32_t bitmap_allocs;
-			struct {
-				short bit;
-				unsigned short quanta;
-			} *bitm_alloc;
-		} bitmap;
-
-		struct {
-			unsigned long used;      /* Bytes currently allocated */
-			struct list_head alist;  /* List of allocations       */
-		} system_mem;
-	} allocator;
-
-	int id;
-	struct kobject kobj;
-
-	/* for debugging, creates a list of pmem file structs, the
-	 * data_list_mutex should be taken before pmem_data->sem if both are
-	 * needed */
-	struct mutex data_list_mutex;
-	struct list_head data_list;
-	/* arena_mutex protects the global allocation arena
-	 *
-	 * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER:
-	 * down(pmem_data->sem) => mutex_lock(arena_mutex)
-	 */
-	struct mutex arena_mutex;
-
-	long (*ioctl)(struct file *, unsigned int, unsigned long);
-	int (*release)(struct inode *, struct file *);
-	/* reference count of allocations */
-	atomic_t allocation_cnt;
-	/*
-	 * request function for a region when the allocation count goes
-	 * from 0 -> 1
-	 */
-	int (*mem_request)(void *);
-	/*
-	 * release function for a region when the allocation count goes
-	 * from 1 -> 0
-	 */
-	int (*mem_release)(void *);
-	/*
-	 * private data for the request/release callback
-	 */
-	void *region_data;
-	/*
-	 * map and unmap as needed
-	 */
-	int map_on_demand;
-	/*
-	 * memory will be reused through fmem
-	 */
-	int reusable;
-};
-#define to_pmem_info_id(a) (container_of(a, struct pmem_info, kobj)->id)
-
-static void ioremap_pmem(int id);
-static void pmem_put_region(int id);
-static int pmem_get_region(int id);
-
-static struct pmem_info pmem[PMEM_MAX_DEVICES];
-static int id_count;
-
-#define PMEM_SYSFS_DIR_NAME "pmem_regions" /* under /sys/kernel/ */
-static struct kset *pmem_kset;
-
-#define PMEM_IS_FREE_BUDDY(id, index) \
-	(!(pmem[id].allocator.buddy_bestfit.buddy_bitmap[index].allocated))
-#define PMEM_BUDDY_ORDER(id, index) \
-	(pmem[id].allocator.buddy_bestfit.buddy_bitmap[index].order)
-#define PMEM_BUDDY_INDEX(id, index) \
-	(index ^ (1 << PMEM_BUDDY_ORDER(id, index)))
-#define PMEM_BUDDY_NEXT_INDEX(id, index) \
-	(index + (1 << PMEM_BUDDY_ORDER(id, index)))
-#define PMEM_OFFSET(index) (index * pmem[id].quantum)
-#define PMEM_START_ADDR(id, index) \
-	(PMEM_OFFSET(index) + pmem[id].base)
-#define PMEM_BUDDY_LEN(id, index) \
-	((1 << PMEM_BUDDY_ORDER(id, index)) * pmem[id].quantum)
-#define PMEM_END_ADDR(id, index) \
-	(PMEM_START_ADDR(id, index) + PMEM_LEN(id, index))
-#define PMEM_START_VADDR(id, index) \
-	(PMEM_OFFSET(id, index) + pmem[id].vbase)
-#define PMEM_END_VADDR(id, index) \
-	(PMEM_START_VADDR(id, index) + PMEM_LEN(id, index))
-#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED)
-#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
-#define PMEM_IS_SUBMAP(data) \
-	((data->flags & PMEM_FLAGS_SUBMAP) && \
-	(!(data->flags & PMEM_FLAGS_UNSUBMAP)))
-
-static int pmem_release(struct inode *, struct file *);
-static int pmem_mmap(struct file *, struct vm_area_struct *);
-static int pmem_open(struct inode *, struct file *);
-static long pmem_ioctl(struct file *, unsigned int, unsigned long);
-
-struct file_operations pmem_fops = {
-	.release = pmem_release,
-	.mmap = pmem_mmap,
-	.open = pmem_open,
-	.unlocked_ioctl = pmem_ioctl,
-};
-
-#define PMEM_ATTR(_name, _mode, _show, _store) {            \
-	.attr = {.name = __stringify(_name), .mode = _mode }, \
-	.show = _show,                                        \
-	.store = _store,                                      \
-}
-
-struct pmem_attr {
-	struct attribute attr;
-	ssize_t(*show) (const int id, char * const);
-	ssize_t(*store) (const int id, const char * const, const size_t count);
-};
-#define to_pmem_attr(a) container_of(a, struct pmem_attr, attr)
-
-#define RW_PMEM_ATTR(name)  \
-static struct pmem_attr pmem_attr_## name = \
- PMEM_ATTR(name, S_IRUGO | S_IWUSR, show_pmem_## name, store_pmem_## name)
-
-#define RO_PMEM_ATTR(name)  \
-static struct pmem_attr pmem_attr_## name = \
- PMEM_ATTR(name, S_IRUGO, show_pmem_## name, NULL)
-
-#define WO_PMEM_ATTR(name)  \
-static struct pmem_attr pmem_attr_## name = \
- PMEM_ATTR(name, S_IWUSR, NULL, store_pmem_## name)
-
-static ssize_t show_pmem(struct kobject *kobj,
-			struct attribute *attr,
-			char *buf)
-{
-	struct pmem_attr *a = to_pmem_attr(attr);
-	return a->show ? a->show(to_pmem_info_id(kobj), buf) : -EIO;
-}
-
-static ssize_t store_pmem(struct kobject *kobj, struct attribute *attr,
-		     const char *buf, size_t count)
-{
-	struct pmem_attr *a = to_pmem_attr(attr);
-	return a->store ? a->store(to_pmem_info_id(kobj), buf, count) : -EIO;
-}
-
-static struct sysfs_ops pmem_ops = {
-	.show = show_pmem,
-	.store = store_pmem,
-};
-
-static ssize_t show_pmem_base(int id, char *buf)
-{
-	return scnprintf(buf, PAGE_SIZE, "%lu(%#lx)\n",
-		pmem[id].base, pmem[id].base);
-}
-RO_PMEM_ATTR(base);
-
-static ssize_t show_pmem_size(int id, char *buf)
-{
-	return scnprintf(buf, PAGE_SIZE, "%lu(%#lx)\n",
-		pmem[id].size, pmem[id].size);
-}
-RO_PMEM_ATTR(size);
-
-static ssize_t show_pmem_allocator_type(int id, char *buf)
-{
-	switch (pmem[id].allocator_type) {
-	case  PMEM_ALLOCATORTYPE_ALLORNOTHING:
-		return scnprintf(buf, PAGE_SIZE, "%s\n", "All or Nothing");
-	case  PMEM_ALLOCATORTYPE_BUDDYBESTFIT:
-		return scnprintf(buf, PAGE_SIZE, "%s\n", "Buddy Bestfit");
-	case  PMEM_ALLOCATORTYPE_BITMAP:
-		return scnprintf(buf, PAGE_SIZE, "%s\n", "Bitmap");
-	case PMEM_ALLOCATORTYPE_SYSTEM:
-		return scnprintf(buf, PAGE_SIZE, "%s\n", "System heap");
-	default:
-		return scnprintf(buf, PAGE_SIZE,
-			"??? Invalid allocator type (%d) for this region! "
-			"Something isn't right.\n",
-			pmem[id].allocator_type);
-	}
-}
-RO_PMEM_ATTR(allocator_type);
-
-static ssize_t show_pmem_mapped_regions(int id, char *buf)
-{
-	struct list_head *elt;
-	int ret;
-
-	ret = scnprintf(buf, PAGE_SIZE,
-		      "pid #: mapped regions (offset, len) (offset,len)...\n");
-
-	mutex_lock(&pmem[id].data_list_mutex);
-	list_for_each(elt, &pmem[id].data_list) {
-		struct pmem_data *data =
-			list_entry(elt, struct pmem_data, list);
-		struct list_head *elt2;
-
-		down_read(&data->sem);
-		ret += scnprintf(buf + ret, PAGE_SIZE - ret, "pid %u:",
-				data->pid);
-		list_for_each(elt2, &data->region_list) {
-			struct pmem_region_node *region_node = list_entry(elt2,
-					struct pmem_region_node,
-					list);
-			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-					"(%lx,%lx) ",
-					region_node->region.offset,
-					region_node->region.len);
-		}
-		up_read(&data->sem);
-		ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
-	}
-	mutex_unlock(&pmem[id].data_list_mutex);
-	return ret;
-}
-RO_PMEM_ATTR(mapped_regions);
-
-#define PMEM_COMMON_SYSFS_ATTRS \
-	&pmem_attr_base.attr, \
-	&pmem_attr_size.attr, \
-	&pmem_attr_allocator_type.attr, \
-	&pmem_attr_mapped_regions.attr
-
-
-static ssize_t show_pmem_allocated(int id, char *buf)
-{
-	ssize_t ret;
-
-	mutex_lock(&pmem[id].arena_mutex);
-	ret = scnprintf(buf, PAGE_SIZE, "%s\n",
-		pmem[id].allocator.all_or_nothing.allocated ?
-		"is allocated" : "is NOT allocated");
-	mutex_unlock(&pmem[id].arena_mutex);
-	return ret;
-}
-RO_PMEM_ATTR(allocated);
-
-static struct attribute *pmem_allornothing_attrs[] = {
-	PMEM_COMMON_SYSFS_ATTRS,
-
-	&pmem_attr_allocated.attr,
-
-	NULL
-};
-
-static struct kobj_type pmem_allornothing_ktype = {
-	.sysfs_ops = &pmem_ops,
-	.default_attrs = pmem_allornothing_attrs,
-};
-
-static ssize_t show_pmem_total_entries(int id, char *buf)
-{
-	return scnprintf(buf, PAGE_SIZE, "%lu\n", pmem[id].num_entries);
-}
-RO_PMEM_ATTR(total_entries);
-
-static ssize_t show_pmem_quantum_size(int id, char *buf)
-{
-	return scnprintf(buf, PAGE_SIZE, "%u (%#x)\n",
-		pmem[id].quantum, pmem[id].quantum);
-}
-RO_PMEM_ATTR(quantum_size);
-
-static ssize_t show_pmem_buddy_bitmap_dump(int id, char *buf)
-{
-	int ret, i;
-
-	mutex_lock(&pmem[id].data_list_mutex);
-	ret = scnprintf(buf, PAGE_SIZE, "index\torder\tlength\tallocated\n");
-
-	for (i = 0; i < pmem[id].num_entries && (PAGE_SIZE - ret);
-			i = PMEM_BUDDY_NEXT_INDEX(id, i))
-		ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d\t%d\t%d\t%d\n",
-			i, PMEM_BUDDY_ORDER(id, i),
-			PMEM_BUDDY_LEN(id, i),
-			!PMEM_IS_FREE_BUDDY(id, i));
-
-	mutex_unlock(&pmem[id].data_list_mutex);
-	return ret;
-}
-RO_PMEM_ATTR(buddy_bitmap_dump);
-
-#define PMEM_BITMAP_BUDDY_BESTFIT_COMMON_SYSFS_ATTRS \
-	&pmem_attr_quantum_size.attr, \
-	&pmem_attr_total_entries.attr
-
-static struct attribute *pmem_buddy_bestfit_attrs[] = {
-	PMEM_COMMON_SYSFS_ATTRS,
-
-	PMEM_BITMAP_BUDDY_BESTFIT_COMMON_SYSFS_ATTRS,
-
-	&pmem_attr_buddy_bitmap_dump.attr,
-
-	NULL
-};
-
-static struct kobj_type pmem_buddy_bestfit_ktype = {
-	.sysfs_ops = &pmem_ops,
-	.default_attrs = pmem_buddy_bestfit_attrs,
-};
-
-static ssize_t show_pmem_free_quanta(int id, char *buf)
-{
-	ssize_t ret;
-
-	mutex_lock(&pmem[id].arena_mutex);
-	ret = scnprintf(buf, PAGE_SIZE, "%u\n",
-		pmem[id].allocator.bitmap.bitmap_free);
-	mutex_unlock(&pmem[id].arena_mutex);
-	return ret;
-}
-RO_PMEM_ATTR(free_quanta);
-
-static ssize_t show_pmem_bits_allocated(int id, char *buf)
-{
-	ssize_t ret;
-	unsigned int i;
-
-	mutex_lock(&pmem[id].arena_mutex);
-
-	ret = scnprintf(buf, PAGE_SIZE,
-		"id: %d\nbitnum\tindex\tquanta allocated\n", id);
-
-	for (i = 0; i < pmem[id].allocator.bitmap.bitmap_allocs; i++)
-		if (pmem[id].allocator.bitmap.bitm_alloc[i].bit != -1)
-			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-				"%u\t%u\t%u\n",
-				i,
-				pmem[id].allocator.bitmap.bitm_alloc[i].bit,
-				pmem[id].allocator.bitmap.bitm_alloc[i].quanta
-				);
-
-	mutex_unlock(&pmem[id].arena_mutex);
-	return ret;
-}
-RO_PMEM_ATTR(bits_allocated);
-
-static struct attribute *pmem_bitmap_attrs[] = {
-	PMEM_COMMON_SYSFS_ATTRS,
-
-	PMEM_BITMAP_BUDDY_BESTFIT_COMMON_SYSFS_ATTRS,
-
-	&pmem_attr_free_quanta.attr,
-	&pmem_attr_bits_allocated.attr,
-
-	NULL
-};
-
-static struct attribute *pmem_system_attrs[] = {
-	PMEM_COMMON_SYSFS_ATTRS,
-
-	NULL
-};
-
-static struct kobj_type pmem_bitmap_ktype = {
-	.sysfs_ops = &pmem_ops,
-	.default_attrs = pmem_bitmap_attrs,
-};
-
-static struct kobj_type pmem_system_ktype = {
-	.sysfs_ops = &pmem_ops,
-	.default_attrs = pmem_system_attrs,
-};
-
-static int pmem_allocate_from_id(const int id, const unsigned long size,
-						const unsigned int align)
-{
-	int ret;
-	ret = pmem_get_region(id);
-
-	if (ret)
-		return -1;
-
-	ret = pmem[id].allocate(id, size, align);
-
-	if (ret < 0)
-		pmem_put_region(id);
-
-	return ret;
-}
-
-static int pmem_free_from_id(const int id, const int index)
-{
-	pmem_put_region(id);
-	return pmem[id].free(id, index);
-}
-
-static int pmem_get_region(int id)
-{
-	/* Must be called with arena mutex locked */
-	atomic_inc(&pmem[id].allocation_cnt);
-	if (!pmem[id].vbase) {
-		DLOG("PMEMDEBUG: mapping for %s", pmem[id].name);
-		if (pmem[id].mem_request) {
-			int ret = pmem[id].mem_request(pmem[id].region_data);
-			if (ret) {
-				atomic_dec(&pmem[id].allocation_cnt);
-				return 1;
-			}
-		}
-		ioremap_pmem(id);
-	}
-
-	if (pmem[id].vbase) {
-		return 0;
-	} else {
-		if (pmem[id].mem_release)
-			pmem[id].mem_release(pmem[id].region_data);
-		atomic_dec(&pmem[id].allocation_cnt);
-		return 1;
-	}
-}
-
-static void pmem_put_region(int id)
-{
-	/* Must be called with arena mutex locked */
-	if (atomic_dec_and_test(&pmem[id].allocation_cnt)) {
-		DLOG("PMEMDEBUG: unmapping for %s", pmem[id].name);
-		BUG_ON(!pmem[id].vbase);
-		if (pmem[id].map_on_demand) {
-			/* unmap_kernel_range() flushes the caches
-			 * and removes the page table entries
-			 */
-			unmap_kernel_range((unsigned long)pmem[id].vbase,
-				 pmem[id].size);
-			pmem[id].vbase = NULL;
-			if (pmem[id].mem_release) {
-				int ret = pmem[id].mem_release(
-						pmem[id].region_data);
-				WARN(ret, "mem_release failed");
-			}
-
-		}
-	}
-}
-
-static int get_id(struct file *file)
-{
-	return MINOR(file->f_dentry->d_inode->i_rdev);
-}
-
-static char *get_name(struct file *file)
-{
-	int id = get_id(file);
-	return pmem[id].name;
-}
-
-static int is_pmem_file(struct file *file)
-{
-	int id;
-
-	if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))
-		return 0;
-
-	id = get_id(file);
-	return (unlikely(id >= PMEM_MAX_DEVICES ||
-		file->f_dentry->d_inode->i_rdev !=
-		     MKDEV(MISC_MAJOR, pmem[id].dev.minor))) ? 0 : 1;
-}
-
-static int has_allocation(struct file *file)
-{
-	/* must be called with at least read lock held on
-	 * ((struct pmem_data *)(file->private_data))->sem which
-	 * means that file is guaranteed not to be NULL upon entry!!
-	 * check is_pmem_file first if not accessed via pmem_file_ops */
-	struct pmem_data *pdata = file->private_data;
-	return pdata && pdata->index != -1;
-}
-
-static int is_master_owner(struct file *file)
-{
-	struct file *master_file;
-	struct pmem_data *data = file->private_data;
-	int put_needed, ret = 0;
-
-	if (!has_allocation(file))
-		return 0;
-	if (PMEM_FLAGS_MASTERMAP & data->flags)
-		return 1;
-	master_file = fget_light(data->master_fd, &put_needed);
-	if (master_file && data->master_file == master_file)
-		ret = 1;
-	if (master_file)
-		fput_light(master_file, put_needed);
-	return ret;
-}
-
-static int pmem_free_all_or_nothing(int id, int index)
-{
-	/* caller should hold the lock on arena_mutex! */
-	DLOG("index %d\n", index);
-
-	pmem[id].allocator.all_or_nothing.allocated =  0;
-	return 0;
-}
-
-static int pmem_free_space_all_or_nothing(int id,
-		struct pmem_freespace *fs)
-{
-	/* caller should hold the lock on arena_mutex! */
-	fs->total = (unsigned long)
-		pmem[id].allocator.all_or_nothing.allocated == 0 ?
-		pmem[id].size : 0;
-
-	fs->largest = fs->total;
-	return 0;
-}
-
-
-static int pmem_free_buddy_bestfit(int id, int index)
-{
-	/* caller should hold the lock on arena_mutex! */
-	int curr = index;
-	DLOG("index %d\n", index);
-
-
-	/* clean up the bitmap, merging any buddies */
-	pmem[id].allocator.buddy_bestfit.buddy_bitmap[curr].allocated = 0;
-	/* find a slots buddy Buddy# = Slot# ^ (1 << order)
-	 * if the buddy is also free merge them
-	 * repeat until the buddy is not free or end of the bitmap is reached
-	 */
-	do {
-		int buddy = PMEM_BUDDY_INDEX(id, curr);
-		if (buddy < pmem[id].num_entries &&
-		    PMEM_IS_FREE_BUDDY(id, buddy) &&
-		    PMEM_BUDDY_ORDER(id, buddy) ==
-				PMEM_BUDDY_ORDER(id, curr)) {
-			PMEM_BUDDY_ORDER(id, buddy)++;
-			PMEM_BUDDY_ORDER(id, curr)++;
-			curr = min(buddy, curr);
-		} else {
-			break;
-		}
-	} while (curr < pmem[id].num_entries);
-
-	return 0;
-}
-
-
-static int pmem_free_space_buddy_bestfit(int id,
-		struct pmem_freespace *fs)
-{
-	/* caller should hold the lock on arena_mutex! */
-	int curr;
-	unsigned long size;
-	fs->total = 0;
-	fs->largest = 0;
-
-	for (curr = 0; curr < pmem[id].num_entries;
-	     curr = PMEM_BUDDY_NEXT_INDEX(id, curr)) {
-		if (PMEM_IS_FREE_BUDDY(id, curr)) {
-			size = PMEM_BUDDY_LEN(id, curr);
-			if (size > fs->largest)
-				fs->largest = size;
-			fs->total += size;
-		}
-	}
-	return 0;
-}
-
-
-static inline uint32_t start_mask(int bit_start)
-{
-	return (uint32_t)(~0) << (bit_start & PMEM_BITS_PER_WORD_MASK);
-}
-
-static inline uint32_t end_mask(int bit_end)
-{
-	return (uint32_t)(~0) >>
-		((BITS_PER_LONG - bit_end) & PMEM_BITS_PER_WORD_MASK);
-}
-
-static inline int compute_total_words(int bit_end, int word_index)
-{
-	return ((bit_end + BITS_PER_LONG - 1) >>
-			PMEM_32BIT_WORD_ORDER) - word_index;
-}
-
-static void bitmap_bits_clear_all(uint32_t *bitp, int bit_start, int bit_end)
-{
-	int word_index = bit_start >> PMEM_32BIT_WORD_ORDER, total_words;
-
-	total_words = compute_total_words(bit_end, word_index);
-	if (total_words > 0) {
-		if (total_words == 1) {
-			bitp[word_index] &=
-				~(start_mask(bit_start) & end_mask(bit_end));
-		} else {
-			bitp[word_index++] &= ~start_mask(bit_start);
-			if (total_words > 2) {
-				int total_bytes;
-
-				total_words -= 2;
-				total_bytes = total_words << 2;
-
-				memset(&bitp[word_index], 0, total_bytes);
-				word_index += total_words;
-			}
-			bitp[word_index] &= ~end_mask(bit_end);
-		}
-	}
-}
-
-static int pmem_free_bitmap(int id, int bitnum)
-{
-	/* caller should hold the lock on arena_mutex! */
-	int i;
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-
-	DLOG("bitnum %d\n", bitnum);
-
-	for (i = 0; i < pmem[id].allocator.bitmap.bitmap_allocs; i++) {
-		const int curr_bit =
-			pmem[id].allocator.bitmap.bitm_alloc[i].bit;
-
-		if (curr_bit == bitnum) {
-			const int curr_quanta =
-				pmem[id].allocator.bitmap.bitm_alloc[i].quanta;
-
-			bitmap_bits_clear_all(pmem[id].allocator.bitmap.bitmap,
-				curr_bit, curr_bit + curr_quanta);
-			pmem[id].allocator.bitmap.bitmap_free += curr_quanta;
-			pmem[id].allocator.bitmap.bitm_alloc[i].bit = -1;
-			pmem[id].allocator.bitmap.bitm_alloc[i].quanta = 0;
-			return 0;
-		}
-	}
-	printk(KERN_ALERT "pmem: %s: Attempt to free unallocated index %d, id"
-		" %d, pid %d(%s)\n", __func__, bitnum, id,  current->pid,
-		get_task_comm(currtask_name, current));
-
-	return -1;
-}
-
-static int pmem_free_system(int id, int index)
-{
-	/* caller should hold the lock on arena_mutex! */
-	struct alloc_list *item;
-
-	DLOG("index %d\n", index);
-	if (index != 0)
-		item = (struct alloc_list *)index;
-	else
-		return 0;
-
-	if (item->vaddr != NULL) {
-		iounmap(item->vaddr);
-		kfree(__va(item->addr));
-		list_del(&item->allocs);
-		kfree(item);
-	}
-
-	return 0;
-}
-
-static int pmem_free_space_bitmap(int id, struct pmem_freespace *fs)
-{
-	int i, j;
-	int max_allocs = pmem[id].allocator.bitmap.bitmap_allocs;
-	int alloc_start = 0;
-	int next_alloc;
-	unsigned long size = 0;
-
-	fs->total = 0;
-	fs->largest = 0;
-
-	for (i = 0; i < max_allocs; i++) {
-
-		int alloc_quanta = 0;
-		int alloc_idx = 0;
-		next_alloc = pmem[id].num_entries;
-
-		/* Look for the lowest bit where next allocation starts */
-		for (j = 0; j < max_allocs; j++) {
-			const int curr_alloc = pmem[id].allocator.
-						bitmap.bitm_alloc[j].bit;
-			if (curr_alloc != -1) {
-				if (alloc_start == curr_alloc)
-					alloc_idx = j;
-				if (alloc_start >= curr_alloc)
-					continue;
-				if (curr_alloc < next_alloc)
-					next_alloc = curr_alloc;
-			}
-		}
-		alloc_quanta = pmem[id].allocator.bitmap.
-				bitm_alloc[alloc_idx].quanta;
-		size = (next_alloc - (alloc_start + alloc_quanta)) *
-				pmem[id].quantum;
-
-		if (size > fs->largest)
-			fs->largest = size;
-		fs->total += size;
-
-		if (next_alloc == pmem[id].num_entries)
-			break;
-		else
-			alloc_start = next_alloc;
-	}
-
-	return 0;
-}
-
-static int pmem_free_space_system(int id, struct pmem_freespace *fs)
-{
-	fs->total = pmem[id].size;
-	fs->largest = pmem[id].size;
-
-	return 0;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data);
-
-static int pmem_release(struct inode *inode, struct file *file)
-{
-	struct pmem_data *data = file->private_data;
-	struct pmem_region_node *region_node;
-	struct list_head *elt, *elt2;
-	int id = get_id(file), ret = 0;
-
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-	DLOG("releasing memory pid %u(%s) file %p(%ld) dev %s(id: %d)\n",
-		current->pid, get_task_comm(currtask_name, current),
-		file, file_count(file), get_name(file), id);
-	mutex_lock(&pmem[id].data_list_mutex);
-	/* if this file is a master, revoke all the memory in the connected
-	 *  files */
-	if (PMEM_FLAGS_MASTERMAP & data->flags) {
-		list_for_each(elt, &pmem[id].data_list) {
-			struct pmem_data *sub_data =
-				list_entry(elt, struct pmem_data, list);
-			int is_master;
-
-			down_read(&sub_data->sem);
-			is_master = (PMEM_IS_SUBMAP(sub_data) &&
-				file == sub_data->master_file);
-			up_read(&sub_data->sem);
-
-			if (is_master)
-				pmem_revoke(file, sub_data);
-		}
-	}
-	list_del(&data->list);
-	mutex_unlock(&pmem[id].data_list_mutex);
-
-	down_write(&data->sem);
-
-	/* if it is not a connected file and it has an allocation, free it */
-	if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) {
-		mutex_lock(&pmem[id].arena_mutex);
-		ret = pmem_free_from_id(id, data->index);
-		mutex_unlock(&pmem[id].arena_mutex);
-	}
-
-	/* if this file is a submap (mapped, connected file), downref the
-	 * task struct */
-	if (PMEM_FLAGS_SUBMAP & data->flags)
-		if (data->task) {
-			put_task_struct(data->task);
-			data->task = NULL;
-		}
-
-	file->private_data = NULL;
-
-	list_for_each_safe(elt, elt2, &data->region_list) {
-		region_node = list_entry(elt, struct pmem_region_node, list);
-		list_del(elt);
-		kfree(region_node);
-	}
-	BUG_ON(!list_empty(&data->region_list));
-
-	up_write(&data->sem);
-	kfree(data);
-	if (pmem[id].release)
-		ret = pmem[id].release(inode, file);
-
-	return ret;
-}
-
-static int pmem_open(struct inode *inode, struct file *file)
-{
-	struct pmem_data *data;
-	int id = get_id(file);
-	int ret = 0;
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-
-	DLOG("pid %u(%s) file %p(%ld) dev %s(id: %d)\n",
-		current->pid, get_task_comm(currtask_name, current),
-		file, file_count(file), get_name(file), id);
-	data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL);
-	if (!data) {
-		printk(KERN_ALERT "pmem: %s: unable to allocate memory for "
-				"pmem metadata.", __func__);
-		return -1;
-	}
-	data->flags = 0;
-	data->index = -1;
-	data->task = NULL;
-	data->vma = NULL;
-	data->pid = 0;
-	data->master_file = NULL;
-#if PMEM_DEBUG
-	data->ref = 0;
-#endif
-	INIT_LIST_HEAD(&data->region_list);
-	init_rwsem(&data->sem);
-
-	file->private_data = data;
-	INIT_LIST_HEAD(&data->list);
-
-	mutex_lock(&pmem[id].data_list_mutex);
-	list_add(&data->list, &pmem[id].data_list);
-	mutex_unlock(&pmem[id].data_list_mutex);
-	return ret;
-}
-
-static unsigned long pmem_order(unsigned long len, int id)
-{
-	int i;
-
-	len = (len + pmem[id].quantum - 1)/pmem[id].quantum;
-	len--;
-	for (i = 0; i < sizeof(len)*8; i++)
-		if (len >> i == 0)
-			break;
-	return i;
-}
-
-static int pmem_allocator_all_or_nothing(const int id,
-		const unsigned long len,
-		const unsigned int align)
-{
-	/* caller should hold the lock on arena_mutex! */
-	DLOG("all or nothing\n");
-	if ((len > pmem[id].size) ||
-		pmem[id].allocator.all_or_nothing.allocated)
-		return -1;
-	pmem[id].allocator.all_or_nothing.allocated = 1;
-	return len;
-}
-
-static int pmem_allocator_buddy_bestfit(const int id,
-		const unsigned long len,
-		unsigned int align)
-{
-	/* caller should hold the lock on arena_mutex! */
-	int curr;
-	int best_fit = -1;
-	unsigned long order;
-
-	DLOG("buddy bestfit\n");
-	order = pmem_order(len, id);
-	if (order > PMEM_MAX_ORDER)
-		goto out;
-
-	DLOG("order %lx\n", order);
-
-	/* Look through the bitmap.
-	 * 	If a free slot of the correct order is found, use it.
-	 * 	Otherwise, use the best fit (smallest with size > order) slot.
-	 */
-	for (curr = 0;
-	     curr < pmem[id].num_entries;
-	     curr = PMEM_BUDDY_NEXT_INDEX(id, curr))
-		if (PMEM_IS_FREE_BUDDY(id, curr)) {
-			if (PMEM_BUDDY_ORDER(id, curr) ==
-					(unsigned char)order) {
-				/* set the not free bit and clear others */
-				best_fit = curr;
-				break;
-			}
-			if (PMEM_BUDDY_ORDER(id, curr) >
-					(unsigned char)order &&
-			    (best_fit < 0 ||
-			     PMEM_BUDDY_ORDER(id, curr) <
-					PMEM_BUDDY_ORDER(id, best_fit)))
-				best_fit = curr;
-		}
-
-	/* if best_fit < 0, there are no suitable slots; return an error */
-	if (best_fit < 0) {
-#if PMEM_DEBUG
-		printk(KERN_ALERT "pmem: %s: no space left to allocate!\n",
-			__func__);
-#endif
-		goto out;
-	}
-
-	/* now partition the best fit:
-	 * 	split the slot into 2 buddies of order - 1
-	 * 	repeat until the slot is of the correct order
-	 */
-	while (PMEM_BUDDY_ORDER(id, best_fit) > (unsigned char)order) {
-		int buddy;
-		PMEM_BUDDY_ORDER(id, best_fit) -= 1;
-		buddy = PMEM_BUDDY_INDEX(id, best_fit);
-		PMEM_BUDDY_ORDER(id, buddy) = PMEM_BUDDY_ORDER(id, best_fit);
-	}
-	pmem[id].allocator.buddy_bestfit.buddy_bitmap[best_fit].allocated = 1;
-out:
-	return best_fit;
-}
-
-
-static inline unsigned long paddr_from_bit(const int id, const int bitnum)
-{
-	return pmem[id].base + pmem[id].quantum * bitnum;
-}
-
-static inline unsigned long bit_from_paddr(const int id,
-		const unsigned long paddr)
-{
-	return (paddr - pmem[id].base) / pmem[id].quantum;
-}
-
-static void bitmap_bits_set_all(uint32_t *bitp, int bit_start, int bit_end)
-{
-	int word_index = bit_start >> PMEM_32BIT_WORD_ORDER, total_words;
-
-	total_words = compute_total_words(bit_end, word_index);
-	if (total_words > 0) {
-		if (total_words == 1) {
-			bitp[word_index] |=
-				(start_mask(bit_start) & end_mask(bit_end));
-		} else {
-			bitp[word_index++] |= start_mask(bit_start);
-			if (total_words > 2) {
-				int total_bytes;
-
-				total_words -= 2;
-				total_bytes = total_words << 2;
-
-				memset(&bitp[word_index], ~0, total_bytes);
-				word_index += total_words;
-			}
-			bitp[word_index] |= end_mask(bit_end);
-		}
-	}
-}
-
-static int
-bitmap_allocate_contiguous(uint32_t *bitp, int num_bits_to_alloc,
-		int total_bits, int spacing, int start_bit)
-{
-	int bit_start, last_bit, word_index;
-
-	if (num_bits_to_alloc <= 0)
-		return -1;
-
-	for (bit_start = start_bit; ;
-		bit_start = ((last_bit +
-			(word_index << PMEM_32BIT_WORD_ORDER) + spacing - 1)
-			& ~(spacing - 1)) + start_bit) {
-		int bit_end = bit_start + num_bits_to_alloc, total_words;
-
-		if (bit_end > total_bits)
-			return -1; /* out of contiguous memory */
-
-		word_index = bit_start >> PMEM_32BIT_WORD_ORDER;
-		total_words = compute_total_words(bit_end, word_index);
-
-		if (total_words <= 0)
-			return -1;
-
-		if (total_words == 1) {
-			last_bit = fls(bitp[word_index] &
-					(start_mask(bit_start) &
-						end_mask(bit_end)));
-			if (last_bit)
-				continue;
-		} else {
-			int end_word = word_index + (total_words - 1);
-			last_bit =
-				fls(bitp[word_index] & start_mask(bit_start));
-			if (last_bit)
-				continue;
-
-			for (word_index++;
-					word_index < end_word;
-					word_index++) {
-				last_bit = fls(bitp[word_index]);
-				if (last_bit)
-					break;
-			}
-			if (last_bit)
-				continue;
-
-			last_bit = fls(bitp[word_index] & end_mask(bit_end));
-			if (last_bit)
-				continue;
-		}
-		bitmap_bits_set_all(bitp, bit_start, bit_end);
-		return bit_start;
-	}
-	return -1;
-}
-
-static int reserve_quanta(const unsigned int quanta_needed,
-		const int id,
-		unsigned int align)
-{
-	/* alignment should be a valid power of 2 */
-	int ret = -1, start_bit = 0, spacing = 1;
-
-	/* Sanity check */
-	if (quanta_needed > pmem[id].allocator.bitmap.bitmap_free) {
-#if PMEM_DEBUG
-		printk(KERN_ALERT "pmem: %s: request (%d) too big for"
-			" available free (%d)\n", __func__, quanta_needed,
-			pmem[id].allocator.bitmap.bitmap_free);
-#endif
-		return -1;
-	}
-
-	start_bit = bit_from_paddr(id,
-		(pmem[id].base + align - 1) & ~(align - 1));
-	if (start_bit <= -1) {
-#if PMEM_DEBUG
-		printk(KERN_ALERT
-			"pmem: %s: bit_from_paddr fails for"
-			" %u alignment.\n", __func__, align);
-#endif
-		return -1;
-	}
-	spacing = align / pmem[id].quantum;
-	spacing = spacing > 1 ? spacing : 1;
-
-	ret = bitmap_allocate_contiguous(pmem[id].allocator.bitmap.bitmap,
-		quanta_needed,
-		(pmem[id].size + pmem[id].quantum - 1) / pmem[id].quantum,
-		spacing,
-		start_bit);
-
-#if PMEM_DEBUG
-	if (ret < 0)
-		printk(KERN_ALERT "pmem: %s: not enough contiguous bits free "
-			"in bitmap! Region memory is either too fragmented or"
-			" request is too large for available memory.\n",
-			__func__);
-#endif
-
-	return ret;
-}
-
-static int pmem_allocator_bitmap(const int id,
-		const unsigned long len,
-		const unsigned int align)
-{
-	/* caller should hold the lock on arena_mutex! */
-	int bitnum, i;
-	unsigned int quanta_needed;
-
-	DLOG("bitmap id %d, len %ld, align %u\n", id, len, align);
-	if (!pmem[id].allocator.bitmap.bitm_alloc) {
-#if PMEM_DEBUG
-		printk(KERN_ALERT "pmem: bitm_alloc not present! id: %d\n",
-			id);
-#endif
-		return -1;
-	}
-
-	quanta_needed = (len + pmem[id].quantum - 1) / pmem[id].quantum;
-	DLOG("quantum size %u quanta needed %u free %u id %d\n",
-		pmem[id].quantum, quanta_needed,
-		pmem[id].allocator.bitmap.bitmap_free, id);
-
-	if (pmem[id].allocator.bitmap.bitmap_free < quanta_needed) {
-#if PMEM_DEBUG
-		printk(KERN_ALERT "pmem: memory allocation failure. "
-			"PMEM memory region exhausted, id %d."
-			" Unable to comply with allocation request.\n", id);
-#endif
-		return -1;
-	}
-
-	bitnum = reserve_quanta(quanta_needed, id, align);
-	if (bitnum == -1)
-		goto leave;
-
-	for (i = 0;
-		i < pmem[id].allocator.bitmap.bitmap_allocs &&
-			pmem[id].allocator.bitmap.bitm_alloc[i].bit != -1;
-		i++)
-		;
-
-	if (i >= pmem[id].allocator.bitmap.bitmap_allocs) {
-		void *temp;
-		int32_t new_bitmap_allocs =
-			pmem[id].allocator.bitmap.bitmap_allocs << 1;
-		int j;
-
-		if (!new_bitmap_allocs) { /* failed sanity check!! */
-#if PMEM_DEBUG
-			pr_alert("pmem: bitmap_allocs number"
-				" wrapped around to zero! Something "
-				"is VERY wrong.\n");
-#endif
-			return -1;
-		}
-
-		if (new_bitmap_allocs > pmem[id].num_entries) {
-			/* failed sanity check!! */
-#if PMEM_DEBUG
-			pr_alert("pmem: required bitmap_allocs"
-				" number exceeds maximum entries possible"
-				" for current quanta\n");
-#endif
-			return -1;
-		}
-
-		temp = krealloc(pmem[id].allocator.bitmap.bitm_alloc,
-				new_bitmap_allocs *
-				sizeof(*pmem[id].allocator.bitmap.bitm_alloc),
-				GFP_KERNEL);
-		if (!temp) {
-#if PMEM_DEBUG
-			pr_alert("pmem: can't realloc bitmap_allocs,"
-				"id %d, current num bitmap allocs %d\n",
-				id, pmem[id].allocator.bitmap.bitmap_allocs);
-#endif
-			return -1;
-		}
-		pmem[id].allocator.bitmap.bitmap_allocs = new_bitmap_allocs;
-		pmem[id].allocator.bitmap.bitm_alloc = temp;
-
-		for (j = i; j < new_bitmap_allocs; j++) {
-			pmem[id].allocator.bitmap.bitm_alloc[j].bit = -1;
-			pmem[id].allocator.bitmap.bitm_alloc[i].quanta = 0;
-		}
-
-		DLOG("increased # of allocated regions to %d for id %d\n",
-			pmem[id].allocator.bitmap.bitmap_allocs, id);
-	}
-
-	DLOG("bitnum %d, bitm_alloc index %d\n", bitnum, i);
-
-	pmem[id].allocator.bitmap.bitmap_free -= quanta_needed;
-	pmem[id].allocator.bitmap.bitm_alloc[i].bit = bitnum;
-	pmem[id].allocator.bitmap.bitm_alloc[i].quanta = quanta_needed;
-leave:
-	return bitnum;
-}
-
-static int pmem_allocator_system(const int id,
-		const unsigned long len,
-		const unsigned int align)
-{
-	/* caller should hold the lock on arena_mutex! */
-	struct alloc_list *list;
-	unsigned long aligned_len;
-	int count = SYSTEM_ALLOC_RETRY;
-	void *buf;
-
-	DLOG("system id %d, len %ld, align %u\n", id, len, align);
-
-	if ((pmem[id].allocator.system_mem.used + len) > pmem[id].size) {
-		DLOG("requested size would be larger than quota\n");
-		return -1;
-	}
-
-	/* Handle alignment */
-	aligned_len = len + align;
-
-	/* Attempt allocation */
-	list = kmalloc(sizeof(struct alloc_list), GFP_KERNEL);
-	if (list == NULL) {
-		printk(KERN_ERR "pmem: failed to allocate system metadata\n");
-		return -1;
-	}
-	list->vaddr = NULL;
-
-	buf = NULL;
-	while ((buf == NULL) && count--) {
-		buf = kmalloc((aligned_len), GFP_KERNEL);
-		if (buf == NULL) {
-			DLOG("pmem: kmalloc %d temporarily failed len= %ld\n",
-				count, aligned_len);
-		}
-	}
-	if (!buf) {
-		printk(KERN_CRIT "pmem: kmalloc failed for id= %d len= %ld\n",
-			id, aligned_len);
-		kfree(list);
-		return -1;
-	}
-	list->size = aligned_len;
-	list->addr = (void *)__pa(buf);
-	list->aaddr = (void *)(((unsigned int)(list->addr) + (align - 1)) &
-			~(align - 1));
-
-	if (!pmem[id].cached)
-		list->vaddr = ioremap(__pa(buf), aligned_len);
-	else
-		list->vaddr = ioremap_cached(__pa(buf), aligned_len);
-
-	INIT_LIST_HEAD(&list->allocs);
-	list_add(&list->allocs, &pmem[id].allocator.system_mem.alist);
-
-	return (int)list;
-}
-
-static pgprot_t pmem_phys_mem_access_prot(struct file *file, pgprot_t vma_prot)
-{
-	int id = get_id(file);
-#ifdef pgprot_writecombine
-	if (pmem[id].cached == 0 || file->f_flags & O_SYNC)
-		/* on ARMv6 and ARMv7 this expands to Normal Noncached */
-		return pgprot_writecombine(vma_prot);
-#endif
-#ifdef pgprot_ext_buffered
-	else if (pmem[id].buffered)
-		return pgprot_ext_buffered(vma_prot);
-#endif
-	return vma_prot;
-}
-
-static unsigned long pmem_start_addr_all_or_nothing(int id,
-		struct pmem_data *data)
-{
-	return PMEM_START_ADDR(id, 0);
-}
-
-static unsigned long pmem_start_addr_buddy_bestfit(int id,
-		struct pmem_data *data)
-{
-	return PMEM_START_ADDR(id, data->index);
-}
-
-static unsigned long pmem_start_addr_bitmap(int id, struct pmem_data *data)
-{
-	return data->index * pmem[id].quantum + pmem[id].base;
-}
-
-static unsigned long pmem_start_addr_system(int id, struct pmem_data *data)
-{
-	return (unsigned long)(((struct alloc_list *)(data->index))->aaddr);
-}
-
-static void *pmem_start_vaddr(int id, struct pmem_data *data)
-{
-	if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_SYSTEM)
-		return ((struct alloc_list *)(data->index))->vaddr;
-	else
-	return pmem[id].start_addr(id, data) - pmem[id].base + pmem[id].vbase;
-}
-
-static unsigned long pmem_len_all_or_nothing(int id, struct pmem_data *data)
-{
-	return data->index;
-}
-
-static unsigned long pmem_len_buddy_bestfit(int id, struct pmem_data *data)
-{
-	return PMEM_BUDDY_LEN(id, data->index);
-}
-
-static unsigned long pmem_len_bitmap(int id, struct pmem_data *data)
-{
-	int i;
-	unsigned long ret = 0;
-
-	mutex_lock(&pmem[id].arena_mutex);
-
-	for (i = 0; i < pmem[id].allocator.bitmap.bitmap_allocs; i++)
-		if (pmem[id].allocator.bitmap.bitm_alloc[i].bit ==
-				data->index) {
-			ret = pmem[id].allocator.bitmap.bitm_alloc[i].quanta *
-				pmem[id].quantum;
-			break;
-		}
-
-	mutex_unlock(&pmem[id].arena_mutex);
-#if PMEM_DEBUG
-	if (i >= pmem[id].allocator.bitmap.bitmap_allocs)
-		pr_alert("pmem: %s: can't find bitnum %d in "
-			"alloc'd array!\n", __func__, data->index);
-#endif
-	return ret;
-}
-
-static unsigned long pmem_len_system(int id, struct pmem_data *data)
-{
-	unsigned long ret = 0;
-
-	mutex_lock(&pmem[id].arena_mutex);
-
-	ret = ((struct alloc_list *)data->index)->size;
-	mutex_unlock(&pmem[id].arena_mutex);
-
-	return ret;
-}
-
-static int pmem_map_garbage(int id, struct vm_area_struct *vma,
-			    struct pmem_data *data, unsigned long offset,
-			    unsigned long len)
-{
-	int i, garbage_pages = len >> PAGE_SHIFT;
-
-	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE;
-	for (i = 0; i < garbage_pages; i++) {
-		if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE),
-		    pmem[id].garbage_pfn))
-			return -EAGAIN;
-	}
-	return 0;
-}
-
-static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma,
-				struct pmem_data *data, unsigned long offset,
-				unsigned long len)
-{
-	int garbage_pages;
-	DLOG("unmap offset %lx len %lx\n", offset, len);
-
-	BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
-
-	garbage_pages = len >> PAGE_SHIFT;
-	zap_page_range(vma, vma->vm_start + offset, len, NULL);
-	pmem_map_garbage(id, vma, data, offset, len);
-	return 0;
-}
-
-static int pmem_map_pfn_range(int id, struct vm_area_struct *vma,
-			      struct pmem_data *data, unsigned long offset,
-			      unsigned long len)
-{
-	int ret;
-	DLOG("map offset %lx len %lx\n", offset, len);
-	BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start));
-	BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end));
-	BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
-	BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset));
-
-	ret = io_remap_pfn_range(vma, vma->vm_start + offset,
-		(pmem[id].start_addr(id, data) + offset) >> PAGE_SHIFT,
-		len, vma->vm_page_prot);
-	if (ret) {
-#if PMEM_DEBUG
-		pr_alert("pmem: %s: io_remap_pfn_range fails with "
-			"return value: %d!\n",	__func__, ret);
-#endif
-
-		ret = -EAGAIN;
-	}
-	return ret;
-}
-
-static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma,
-			      struct pmem_data *data, unsigned long offset,
-			      unsigned long len)
-{
-	/* hold the mm semp for the vma you are modifying when you call this */
-	BUG_ON(!vma);
-	zap_page_range(vma, vma->vm_start + offset, len, NULL);
-	return pmem_map_pfn_range(id, vma, data, offset, len);
-}
-
-static void pmem_vma_open(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct pmem_data *data = file->private_data;
-	int id = get_id(file);
-
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-	DLOG("Dev %s(id: %d) pid %u(%s) ppid %u file %p count %ld\n",
-		get_name(file), id, current->pid,
-		get_task_comm(currtask_name, current),
-		current->parent->pid, file, file_count(file));
-	/* this should never be called as we don't support copying pmem
-	 * ranges via fork */
-	down_read(&data->sem);
-	BUG_ON(!has_allocation(file));
-	/* remap the garbage pages, forkers don't get access to the data */
-	pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end);
-	up_read(&data->sem);
-}
-
-static void pmem_vma_close(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct pmem_data *data = file->private_data;
-
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-	DLOG("Dev %s(id: %d) pid %u(%s) ppid %u file %p count %ld\n",
-		get_name(file), get_id(file), current->pid,
-		get_task_comm(currtask_name, current),
-		current->parent->pid, file, file_count(file));
-
-	if (unlikely(!is_pmem_file(file))) {
-		pr_warning("pmem: something is very wrong, you are "
-		       "closing a vm backing an allocation that doesn't "
-		       "exist!\n");
-		return;
-	}
-
-	down_write(&data->sem);
-	if (unlikely(!has_allocation(file))) {
-		up_write(&data->sem);
-		pr_warning("pmem: something is very wrong, you are "
-		       "closing a vm backing an allocation that doesn't "
-		       "exist!\n");
-		return;
-	}
-	if (data->vma == vma) {
-		data->vma = NULL;
-		if ((data->flags & PMEM_FLAGS_CONNECTED) &&
-		    (data->flags & PMEM_FLAGS_SUBMAP))
-			data->flags |= PMEM_FLAGS_UNSUBMAP;
-	}
-	/* the kernel is going to free this vma now anyway */
-	up_write(&data->sem);
-}
-
-static struct vm_operations_struct vm_ops = {
-	.open = pmem_vma_open,
-	.close = pmem_vma_close,
-};
-
-static int pmem_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct pmem_data *data = file->private_data;
-	int index = -1;
-	unsigned long vma_size =  vma->vm_end - vma->vm_start;
-	int ret = 0, id = get_id(file);
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-
-	if (!data) {
-		pr_err("pmem: Invalid file descriptor, no private data\n");
-		return -EINVAL;
-	}
-	DLOG("pid %u(%s) mmap vma_size %lu on dev %s(id: %d)\n", current->pid,
-		get_task_comm(currtask_name, current), vma_size,
-		get_name(file), id);
-	if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) {
-#if PMEM_DEBUG
-		pr_err("pmem: mmaps must be at offset zero, aligned"
-				" and a multiple of pages_size.\n");
-#endif
-		return -EINVAL;
-	}
-
-	down_write(&data->sem);
-	/* check this file isn't already mmaped, for submaps check this file
-	 * has never been mmaped */
-	if ((data->flags & PMEM_FLAGS_SUBMAP) ||
-	    (data->flags & PMEM_FLAGS_UNSUBMAP)) {
-#if PMEM_DEBUG
-		pr_err("pmem: you can only mmap a pmem file once, "
-		       "this file is already mmaped. %x\n", data->flags);
-#endif
-		ret = -EINVAL;
-		goto error;
-	}
-	/* if file->private_data == unalloced, alloc*/
-	if (data->index == -1) {
-		mutex_lock(&pmem[id].arena_mutex);
-		index = pmem_allocate_from_id(id,
-				vma->vm_end - vma->vm_start,
-				SZ_4K);
-		mutex_unlock(&pmem[id].arena_mutex);
-		/* either no space was available or an error occured */
-		if (index == -1) {
-			pr_err("pmem: mmap unable to allocate memory"
-				"on %s\n", get_name(file));
-			ret = -ENOMEM;
-			goto error;
-		}
-		/* store the index of a successful allocation */
-		data->index = index;
-	}
-
-	if (pmem[id].len(id, data) < vma_size) {
-#if PMEM_DEBUG
-		pr_err("pmem: mmap size [%lu] does not match"
-		       " size of backing region [%lu].\n", vma_size,
-		       pmem[id].len(id, data));
-#endif
-		ret = -EINVAL;
-		goto error;
-	}
-
-	vma->vm_pgoff = pmem[id].start_addr(id, data) >> PAGE_SHIFT;
-
-	vma->vm_page_prot = pmem_phys_mem_access_prot(file, vma->vm_page_prot);
-
-	if (data->flags & PMEM_FLAGS_CONNECTED) {
-		struct pmem_region_node *region_node;
-		struct list_head *elt;
-		if (pmem_map_garbage(id, vma, data, 0, vma_size)) {
-			pr_alert("pmem: mmap failed in kernel!\n");
-			ret = -EAGAIN;
-			goto error;
-		}
-		list_for_each(elt, &data->region_list) {
-			region_node = list_entry(elt, struct pmem_region_node,
-						 list);
-			DLOG("remapping file: %p %lx %lx\n", file,
-				region_node->region.offset,
-				region_node->region.len);
-			if (pmem_remap_pfn_range(id, vma, data,
-						 region_node->region.offset,
-						 region_node->region.len)) {
-				ret = -EAGAIN;
-				goto error;
-			}
-		}
-		data->flags |= PMEM_FLAGS_SUBMAP;
-		get_task_struct(current->group_leader);
-		data->task = current->group_leader;
-		data->vma = vma;
-#if PMEM_DEBUG
-		data->pid = current->pid;
-#endif
-		DLOG("submmapped file %p vma %p pid %u\n", file, vma,
-		     current->pid);
-	} else {
-		if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) {
-			pr_err("pmem: mmap failed in kernel!\n");
-			ret = -EAGAIN;
-			goto error;
-		}
-		data->flags |= PMEM_FLAGS_MASTERMAP;
-		data->pid = current->pid;
-	}
-	vma->vm_ops = &vm_ops;
-error:
-	up_write(&data->sem);
-	return ret;
-}
-
-/* the following are the api for accessing pmem regions by other drivers
- * from inside the kernel */
-int get_pmem_user_addr(struct file *file, unsigned long *start,
-		   unsigned long *len)
-{
-	int ret = -1;
-
-	if (is_pmem_file(file)) {
-		struct pmem_data *data = file->private_data;
-
-		down_read(&data->sem);
-		if (has_allocation(file)) {
-			if (data->vma) {
-				*start = data->vma->vm_start;
-				*len = data->vma->vm_end - data->vma->vm_start;
-			} else {
-				*start = *len = 0;
-#if PMEM_DEBUG
-				pr_err("pmem: %s: no vma present.\n",
-					__func__);
-#endif
-			}
-			ret = 0;
-		}
-		up_read(&data->sem);
-	}
-
-#if PMEM_DEBUG
-	if (ret)
-		pr_err("pmem: %s: requested pmem data from invalid"
-			"file.\n", __func__);
-#endif
-	return ret;
-}
-
-int get_pmem_addr(struct file *file, unsigned long *start,
-		  unsigned long *vstart, unsigned long *len)
-{
-	int ret = -1;
-
-	if (is_pmem_file(file)) {
-		struct pmem_data *data = file->private_data;
-
-		down_read(&data->sem);
-		if (has_allocation(file)) {
-			int id = get_id(file);
-
-			*start = pmem[id].start_addr(id, data);
-			*len = pmem[id].len(id, data);
-			*vstart = (unsigned long)
-				pmem_start_vaddr(id, data);
-			up_read(&data->sem);
-#if PMEM_DEBUG
-			down_write(&data->sem);
-			data->ref++;
-			up_write(&data->sem);
-#endif
-			DLOG("returning start %#lx len %lu "
-				"vstart %#lx\n",
-				*start, *len, *vstart);
-			ret = 0;
-		} else {
-			up_read(&data->sem);
-		}
-	}
-	return ret;
-}
-
-int get_pmem_file(unsigned int fd, unsigned long *start, unsigned long *vstart,
-		  unsigned long *len, struct file **filp)
-{
-	int ret = -1;
-	struct file *file = fget(fd);
-
-	if (unlikely(file == NULL)) {
-		pr_err("pmem: %s: requested data from file "
-			"descriptor that doesn't exist.\n", __func__);
-	} else {
-#if PMEM_DEBUG_MSGS
-		char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-		DLOG("filp %p rdev %d pid %u(%s) file %p(%ld)"
-			" dev %s(id: %d)\n", filp,
-			file->f_dentry->d_inode->i_rdev,
-			current->pid, get_task_comm(currtask_name, current),
-			file, file_count(file), get_name(file), get_id(file));
-
-		if (!get_pmem_addr(file, start, vstart, len)) {
-			if (filp)
-				*filp = file;
-			ret = 0;
-		} else {
-			fput(file);
-		}
-	}
-	return ret;
-}
-EXPORT_SYMBOL(get_pmem_file);
-
-int get_pmem_fd(int fd, unsigned long *start, unsigned long *len)
-{
-	unsigned long vstart;
-	return get_pmem_file(fd, start, &vstart, len, NULL);
-}
-EXPORT_SYMBOL(get_pmem_fd);
-
-void put_pmem_file(struct file *file)
-{
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-	DLOG("rdev %d pid %u(%s) file %p(%ld)" " dev %s(id: %d)\n",
-		file->f_dentry->d_inode->i_rdev, current->pid,
-		get_task_comm(currtask_name, current), file,
-		file_count(file), get_name(file), get_id(file));
-	if (is_pmem_file(file)) {
-#if PMEM_DEBUG
-		struct pmem_data *data = file->private_data;
-
-		down_write(&data->sem);
-		if (!data->ref--) {
-			data->ref++;
-			pr_alert("pmem: pmem_put > pmem_get %s "
-				"(pid %d)\n",
-			       pmem[get_id(file)].dev.name, data->pid);
-			BUG();
-		}
-		up_write(&data->sem);
-#endif
-		fput(file);
-	}
-}
-EXPORT_SYMBOL(put_pmem_file);
-
-void put_pmem_fd(int fd)
-{
-	int put_needed;
-	struct file *file = fget_light(fd, &put_needed);
-
-	if (file) {
-		put_pmem_file(file);
-		fput_light(file, put_needed);
-	}
-}
-
-void flush_pmem_fd(int fd, unsigned long offset, unsigned long len)
-{
-	int fput_needed;
-	struct file *file = fget_light(fd, &fput_needed);
-
-	if (file) {
-		flush_pmem_file(file, offset, len);
-		fput_light(file, fput_needed);
-	}
-}
-
-void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
-{
-	struct pmem_data *data;
-	int id;
-	void *vaddr;
-	struct pmem_region_node *region_node;
-	struct list_head *elt;
-	void *flush_start, *flush_end;
-#ifdef CONFIG_OUTER_CACHE
-	unsigned long phy_start, phy_end;
-#endif
-	if (!is_pmem_file(file))
-		return;
-
-	id = get_id(file);
-	if (!pmem[id].cached)
-		return;
-
-	/* is_pmem_file fails if !file */
-	data = file->private_data;
-
-	down_read(&data->sem);
-	if (!has_allocation(file))
-		goto end;
-
-	vaddr = pmem_start_vaddr(id, data);
-
-	if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_SYSTEM) {
-		dmac_flush_range(vaddr,
-			(void *)((unsigned long)vaddr +
-				 ((struct alloc_list *)(data->index))->size));
-#ifdef CONFIG_OUTER_CACHE
-		phy_start = pmem_start_addr_system(id, data);
-
-		phy_end = phy_start +
-			((struct alloc_list *)(data->index))->size;
-
-		outer_flush_range(phy_start, phy_end);
-#endif
-		goto end;
-	}
-	/* if this isn't a submmapped file, flush the whole thing */
-	if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) {
-		dmac_flush_range(vaddr, vaddr + pmem[id].len(id, data));
-#ifdef CONFIG_OUTER_CACHE
-		phy_start = (unsigned long)vaddr -
-				(unsigned long)pmem[id].vbase + pmem[id].base;
-
-		phy_end  =  phy_start + pmem[id].len(id, data);
-
-		outer_flush_range(phy_start, phy_end);
-#endif
-		goto end;
-	}
-	/* otherwise, flush the region of the file we are drawing */
-	list_for_each(elt, &data->region_list) {
-		region_node = list_entry(elt, struct pmem_region_node, list);
-		if ((offset >= region_node->region.offset) &&
-		    ((offset + len) <= (region_node->region.offset +
-			region_node->region.len))) {
-			flush_start = vaddr + region_node->region.offset;
-			flush_end = flush_start + region_node->region.len;
-			dmac_flush_range(flush_start, flush_end);
-#ifdef CONFIG_OUTER_CACHE
-
-			phy_start = (unsigned long)flush_start -
-				(unsigned long)pmem[id].vbase + pmem[id].base;
-
-			phy_end  =  phy_start + region_node->region.len;
-
-			outer_flush_range(phy_start, phy_end);
-#endif
-			break;
-		}
-	}
-end:
-	up_read(&data->sem);
-}
-
-int pmem_cache_maint(struct file *file, unsigned int cmd,
-		struct pmem_addr *pmem_addr)
-{
-	struct pmem_data *data;
-	int id;
-	unsigned long vaddr, paddr, length, offset,
-		      pmem_len, pmem_start_addr;
-
-	/* Called from kernel-space so file may be NULL */
-	if (!file)
-		return -EBADF;
-
-	/*
-	 * check that the vaddr passed for flushing is valid
-	 * so that you don't crash the kernel
-	 */
-	if (!pmem_addr->vaddr)
-		return -EINVAL;
-
-	data = file->private_data;
-	id = get_id(file);
-
-	if (!pmem[id].cached)
-		return 0;
-
-	offset = pmem_addr->offset;
-	length = pmem_addr->length;
-
-	down_read(&data->sem);
-	if (!has_allocation(file)) {
-		up_read(&data->sem);
-		return -EINVAL;
-	}
-	pmem_len = pmem[id].len(id, data);
-	pmem_start_addr = pmem[id].start_addr(id, data);
-	up_read(&data->sem);
-
-	if (offset + length > pmem_len)
-		return -EINVAL;
-
-	vaddr = pmem_addr->vaddr;
-	paddr = pmem_start_addr + offset;
-
-	DLOG("pmem cache maint on dev %s(id: %d)"
-		"(vaddr %lx paddr %lx len %lu bytes)\n",
-		get_name(file), id, vaddr, paddr, length);
-	if (cmd == PMEM_CLEAN_INV_CACHES)
-		clean_and_invalidate_caches(vaddr,
-				length, paddr);
-	else if (cmd == PMEM_CLEAN_CACHES)
-		clean_caches(vaddr, length, paddr);
-	else if (cmd == PMEM_INV_CACHES)
-		invalidate_caches(vaddr, length, paddr);
-
-	return 0;
-}
-EXPORT_SYMBOL(pmem_cache_maint);
-
-static int pmem_connect(unsigned long connect, struct file *file)
-{
-	int ret = 0, put_needed;
-	struct file *src_file;
-
-	if (!file) {
-		pr_err("pmem: %s: NULL file pointer passed in, "
-			"bailing out!\n", __func__);
-		ret = -EINVAL;
-		goto leave;
-	}
-
-	src_file = fget_light(connect, &put_needed);
-
-	if (!src_file) {
-		pr_err("pmem: %s: src file not found!\n", __func__);
-		ret = -EBADF;
-		goto leave;
-	}
-
-	if (src_file == file) { /* degenerative case, operator error */
-		pr_err("pmem: %s: src_file and passed in file are "
-			"the same; refusing to connect to self!\n", __func__);
-		ret = -EINVAL;
-		goto put_src_file;
-	}
-
-	if (unlikely(!is_pmem_file(src_file))) {
-		pr_err("pmem: %s: src file is not a pmem file!\n",
-			__func__);
-		ret = -EINVAL;
-		goto put_src_file;
-	} else {
-		struct pmem_data *src_data = src_file->private_data;
-
-		if (!src_data) {
-			pr_err("pmem: %s: src file pointer has no"
-				"private data, bailing out!\n", __func__);
-			ret = -EINVAL;
-			goto put_src_file;
-		}
-
-		down_read(&src_data->sem);
-
-		if (unlikely(!has_allocation(src_file))) {
-			up_read(&src_data->sem);
-			pr_err("pmem: %s: src file has no allocation!\n",
-				__func__);
-			ret = -EINVAL;
-		} else {
-			struct pmem_data *data;
-			int src_index = src_data->index;
-
-			up_read(&src_data->sem);
-
-			data = file->private_data;
-			if (!data) {
-				pr_err("pmem: %s: passed in file "
-					"pointer has no private data, bailing"
-					" out!\n", __func__);
-				ret = -EINVAL;
-				goto put_src_file;
-			}
-
-			down_write(&data->sem);
-			if (has_allocation(file) &&
-					(data->index != src_index)) {
-				up_write(&data->sem);
-
-				pr_err("pmem: %s: file is already "
-					"mapped but doesn't match this "
-					"src_file!\n", __func__);
-				ret = -EINVAL;
-			} else {
-				data->index = src_index;
-				data->flags |= PMEM_FLAGS_CONNECTED;
-				data->master_fd = connect;
-				data->master_file = src_file;
-
-				up_write(&data->sem);
-
-				DLOG("connect %p to %p\n", file, src_file);
-			}
-		}
-	}
-put_src_file:
-	fput_light(src_file, put_needed);
-leave:
-	return ret;
-}
-
-static void pmem_unlock_data_and_mm(struct pmem_data *data,
-				    struct mm_struct *mm)
-{
-	up_write(&data->sem);
-	if (mm != NULL) {
-		up_write(&mm->mmap_sem);
-		mmput(mm);
-	}
-}
-
-static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data,
-				 struct mm_struct **locked_mm)
-{
-	int ret = 0;
-	struct mm_struct *mm = NULL;
-#if PMEM_DEBUG_MSGS
-	char currtask_name[FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-	DLOG("pid %u(%s) file %p(%ld)\n",
-		current->pid, get_task_comm(currtask_name, current),
-		file, file_count(file));
-
-	*locked_mm = NULL;
-lock_mm:
-	down_read(&data->sem);
-	if (PMEM_IS_SUBMAP(data)) {
-		mm = get_task_mm(data->task);
-		if (!mm) {
-			up_read(&data->sem);
-#if PMEM_DEBUG
-			pr_alert("pmem: can't remap - task is gone!\n");
-#endif
-			return -1;
-		}
-	}
-	up_read(&data->sem);
-
-	if (mm)
-		down_write(&mm->mmap_sem);
-
-	down_write(&data->sem);
-	/* check that the file didn't get mmaped before we could take the
-	 * data sem, this should be safe b/c you can only submap each file
-	 * once */
-	if (PMEM_IS_SUBMAP(data) && !mm) {
-		pmem_unlock_data_and_mm(data, mm);
-		DLOG("mapping contention, repeating mmap op\n");
-		goto lock_mm;
-	}
-	/* now check that vma.mm is still there, it could have been
-	 * deleted by vma_close before we could get the data->sem */
-	if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) {
-		/* might as well release this */
-		if (data->flags & PMEM_FLAGS_SUBMAP) {
-			put_task_struct(data->task);
-			data->task = NULL;
-			/* lower the submap flag to show the mm is gone */
-			data->flags &= ~(PMEM_FLAGS_SUBMAP);
-		}
-		pmem_unlock_data_and_mm(data, mm);
-#if PMEM_DEBUG
-		pr_alert("pmem: vma.mm went away!\n");
-#endif
-		return -1;
-	}
-	*locked_mm = mm;
-	return ret;
-}
-
-int pmem_remap(struct pmem_region *region, struct file *file,
-		      unsigned operation)
-{
-	int ret;
-	struct pmem_region_node *region_node;
-	struct mm_struct *mm = NULL;
-	struct list_head *elt, *elt2;
-	int id = get_id(file);
-	struct pmem_data *data;
-
-	DLOG("operation %#x, region offset %ld, region len %ld\n",
-		operation, region->offset, region->len);
-
-	if (!is_pmem_file(file)) {
-#if PMEM_DEBUG
-		pr_err("pmem: remap request for non-pmem file descriptor\n");
-#endif
-		return -EINVAL;
-	}
-
-	/* is_pmem_file fails if !file */
-	data = file->private_data;
-
-	/* pmem region must be aligned on a page boundry */
-	if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
-		 !PMEM_IS_PAGE_ALIGNED(region->len))) {
-#if PMEM_DEBUG
-		pr_err("pmem: request for unaligned pmem"
-			"suballocation %lx %lx\n",
-			region->offset, region->len);
-#endif
-		return -EINVAL;
-	}
-
-	/* if userspace requests a region of len 0, there's nothing to do */
-	if (region->len == 0)
-		return 0;
-
-	/* lock the mm and data */
-	ret = pmem_lock_data_and_mm(file, data, &mm);
-	if (ret)
-		return 0;
-
-	/* only the owner of the master file can remap the client fds
-	 * that back in it */
-	if (!is_master_owner(file)) {
-#if PMEM_DEBUG
-		pr_err("pmem: remap requested from non-master process\n");
-#endif
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* check that the requested range is within the src allocation */
-	if (unlikely((region->offset > pmem[id].len(id, data)) ||
-		     (region->len > pmem[id].len(id, data)) ||
-		     (region->offset + region->len > pmem[id].len(id, data)))) {
-#if PMEM_DEBUG
-		pr_err("pmem: suballoc doesn't fit in src_file!\n");
-#endif
-		ret = -EINVAL;
-		goto err;
-	}
-
-	if (operation == PMEM_MAP) {
-		region_node = kmalloc(sizeof(struct pmem_region_node),
-			      GFP_KERNEL);
-		if (!region_node) {
-			ret = -ENOMEM;
-#if PMEM_DEBUG
-			pr_alert("pmem: No space to allocate remap metadata!");
-#endif
-			goto err;
-		}
-		region_node->region = *region;
-		list_add(&region_node->list, &data->region_list);
-	} else if (operation == PMEM_UNMAP) {
-		int found = 0;
-		list_for_each_safe(elt, elt2, &data->region_list) {
-			region_node = list_entry(elt, struct pmem_region_node,
-				      list);
-			if (region->len == 0 ||
-			    (region_node->region.offset == region->offset &&
-			    region_node->region.len == region->len)) {
-				list_del(elt);
-				kfree(region_node);
-				found = 1;
-			}
-		}
-		if (!found) {
-#if PMEM_DEBUG
-			pr_err("pmem: Unmap region does not map any"
-				" mapped region!");
-#endif
-			ret = -EINVAL;
-			goto err;
-		}
-	}
-
-	if (data->vma && PMEM_IS_SUBMAP(data)) {
-		if (operation == PMEM_MAP)
-			ret = pmem_remap_pfn_range(id, data->vma, data,
-				   region->offset, region->len);
-		else if (operation == PMEM_UNMAP)
-			ret = pmem_unmap_pfn_range(id, data->vma, data,
-				   region->offset, region->len);
-	}
-
-err:
-	pmem_unlock_data_and_mm(data, mm);
-	return ret;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data)
-{
-	struct pmem_region_node *region_node;
-	struct list_head *elt, *elt2;
-	struct mm_struct *mm = NULL;
-	int id = get_id(file);
-	int ret = 0;
-
-	data->master_file = NULL;
-	ret = pmem_lock_data_and_mm(file, data, &mm);
-	/* if lock_data_and_mm fails either the task that mapped the fd, or
-	 * the vma that mapped it have already gone away, nothing more
-	 * needs to be done */
-	if (ret)
-		return;
-	/* unmap everything */
-	/* delete the regions and region list nothing is mapped any more */
-	if (data->vma)
-		list_for_each_safe(elt, elt2, &data->region_list) {
-			region_node = list_entry(elt, struct pmem_region_node,
-						 list);
-			pmem_unmap_pfn_range(id, data->vma, data,
-					     region_node->region.offset,
-					     region_node->region.len);
-			list_del(elt);
-			kfree(region_node);
-	}
-	/* delete the master file */
-	pmem_unlock_data_and_mm(data, mm);
-}
-
-static void pmem_get_size(struct pmem_region *region, struct file *file)
-{
-	/* called via ioctl file op, so file guaranteed to be not NULL */
-	struct pmem_data *data = file->private_data;
-	int id = get_id(file);
-
-	down_read(&data->sem);
-	if (!has_allocation(file)) {
-		region->offset = 0;
-		region->len = 0;
-	} else {
-		region->offset = pmem[id].start_addr(id, data);
-		region->len = pmem[id].len(id, data);
-	}
-	up_read(&data->sem);
-	DLOG("offset 0x%lx len 0x%lx\n", region->offset, region->len);
-}
-
-
-static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	/* called from user space as file op, so file guaranteed to be not
-	 * NULL
-	 */
-	struct pmem_data *data = file->private_data;
-	int id = get_id(file);
-#if PMEM_DEBUG_MSGS
-	char currtask_name[
-		FIELD_SIZEOF(struct task_struct, comm) + 1];
-#endif
-
-	DLOG("pid %u(%s) file %p(%ld) cmd %#x, dev %s(id: %d)\n",
-		current->pid, get_task_comm(currtask_name, current),
-		file, file_count(file), cmd, get_name(file), id);
-
-	switch (cmd) {
-	case PMEM_GET_PHYS:
-		{
-			struct pmem_region region;
-
-			DLOG("get_phys\n");
-			down_read(&data->sem);
-			if (!has_allocation(file)) {
-				region.offset = 0;
-				region.len = 0;
-			} else {
-				region.offset = pmem[id].start_addr(id, data);
-				region.len = pmem[id].len(id, data);
-			}
-			up_read(&data->sem);
-
-			if (copy_to_user((void __user *)arg, &region,
-						sizeof(struct pmem_region)))
-				return -EFAULT;
-
-			DLOG("pmem: successful request for "
-				"physical address of pmem region id %d, "
-				"offset 0x%lx, len 0x%lx\n",
-				id, region.offset, region.len);
-
-			break;
-		}
-	case PMEM_MAP:
-		{
-			struct pmem_region region;
-			DLOG("map\n");
-			if (copy_from_user(&region, (void __user *)arg,
-						sizeof(struct pmem_region)))
-				return -EFAULT;
-			return pmem_remap(&region, file, PMEM_MAP);
-		}
-		break;
-	case PMEM_UNMAP:
-		{
-			struct pmem_region region;
-			DLOG("unmap\n");
-			if (copy_from_user(&region, (void __user *)arg,
-						sizeof(struct pmem_region)))
-				return -EFAULT;
-			return pmem_remap(&region, file, PMEM_UNMAP);
-			break;
-		}
-	case PMEM_GET_SIZE:
-		{
-			struct pmem_region region;
-			DLOG("get_size\n");
-			pmem_get_size(&region, file);
-			if (copy_to_user((void __user *)arg, &region,
-						sizeof(struct pmem_region)))
-				return -EFAULT;
-			break;
-		}
-	case PMEM_GET_TOTAL_SIZE:
-		{
-			struct pmem_region region;
-			DLOG("get total size\n");
-			region.offset = 0;
-			get_id(file);
-			region.len = pmem[id].size;
-			if (copy_to_user((void __user *)arg, &region,
-						sizeof(struct pmem_region)))
-				return -EFAULT;
-			break;
-		}
-	case PMEM_GET_FREE_SPACE:
-		{
-			struct pmem_freespace fs;
-			DLOG("get freespace on %s(id: %d)\n",
-				get_name(file), id);
-
-			mutex_lock(&pmem[id].arena_mutex);
-			pmem[id].free_space(id, &fs);
-			mutex_unlock(&pmem[id].arena_mutex);
-
-			DLOG("%s(id: %d) total free %lu, largest %lu\n",
-				get_name(file), id, fs.total, fs.largest);
-
-			if (copy_to_user((void __user *)arg, &fs,
-				sizeof(struct pmem_freespace)))
-				return -EFAULT;
-			break;
-	}
-
-	case PMEM_ALLOCATE:
-		{
-			int ret = 0;
-			DLOG("allocate, id %d\n", id);
-			down_write(&data->sem);
-			if (has_allocation(file)) {
-				pr_err("pmem: Existing allocation found on "
-					"this file descrpitor\n");
-				up_write(&data->sem);
-				return -EINVAL;
-			}
-
-			mutex_lock(&pmem[id].arena_mutex);
-			data->index = pmem_allocate_from_id(id,
-					arg,
-					SZ_4K);
-			mutex_unlock(&pmem[id].arena_mutex);
-			ret = data->index == -1 ? -ENOMEM :
-				data->index;
-			up_write(&data->sem);
-			return ret;
-		}
-	case PMEM_ALLOCATE_ALIGNED:
-		{
-			struct pmem_allocation alloc;
-			int ret = 0;
-
-			if (copy_from_user(&alloc, (void __user *)arg,
-						sizeof(struct pmem_allocation)))
-				return -EFAULT;
-			DLOG("allocate id align %d %u\n", id, alloc.align);
-			down_write(&data->sem);
-			if (has_allocation(file)) {
-				pr_err("pmem: Existing allocation found on "
-					"this file descrpitor\n");
-				up_write(&data->sem);
-				return -EINVAL;
-			}
-
-			if (alloc.align & (alloc.align - 1)) {
-				pr_err("pmem: Alignment is not a power of 2\n");
-				return -EINVAL;
-			}
-
-			if (alloc.align != SZ_4K &&
-					(pmem[id].allocator_type !=
-						PMEM_ALLOCATORTYPE_BITMAP)) {
-				pr_err("pmem: Non 4k alignment requires bitmap"
-					" allocator on %s\n", pmem[id].name);
-				return -EINVAL;
-			}
-
-			if (alloc.align > SZ_1M ||
-				alloc.align < SZ_4K) {
-				pr_err("pmem: Invalid Alignment (%u) "
-					"specified\n", alloc.align);
-				return -EINVAL;
-			}
-
-			mutex_lock(&pmem[id].arena_mutex);
-			data->index = pmem_allocate_from_id(id,
-				alloc.size,
-				alloc.align);
-			mutex_unlock(&pmem[id].arena_mutex);
-			ret = data->index == -1 ? -ENOMEM :
-				data->index;
-			up_write(&data->sem);
-			return ret;
-		}
-	case PMEM_CONNECT:
-		DLOG("connect\n");
-		return pmem_connect(arg, file);
-	case PMEM_CLEAN_INV_CACHES:
-	case PMEM_CLEAN_CACHES:
-	case PMEM_INV_CACHES:
-		{
-			struct pmem_addr pmem_addr;
-
-			if (copy_from_user(&pmem_addr, (void __user *)arg,
-						sizeof(struct pmem_addr)))
-				return -EFAULT;
-
-			return pmem_cache_maint(file, cmd, &pmem_addr);
-		}
-	default:
-		if (pmem[id].ioctl)
-			return pmem[id].ioctl(file, cmd, arg);
-
-		DLOG("ioctl invalid (%#x)\n", cmd);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void ioremap_pmem(int id)
-{
-	unsigned long addr;
-	const struct mem_type *type;
-
-	DLOG("PMEMDEBUG: ioremaping for %s\n", pmem[id].name);
-	if (pmem[id].map_on_demand) {
-		addr = (unsigned long)pmem[id].area->addr;
-		if (pmem[id].cached)
-			type = get_mem_type(MT_DEVICE_CACHED);
-		else
-			type = get_mem_type(MT_DEVICE);
-		DLOG("PMEMDEBUG: Remap phys %lx to virt %lx on %s\n",
-			pmem[id].base, addr, pmem[id].name);
-		if (ioremap_pages(addr, pmem[id].base,  pmem[id].size, type)) {
-				pr_err("pmem: Failed to map pages\n");
-				BUG();
-		}
-		pmem[id].vbase = pmem[id].area->addr;
-		/* Flush the cache after installing page table entries to avoid
-		 * aliasing when these pages are remapped to user space.
-		 */
-		flush_cache_vmap(addr, addr + pmem[id].size);
-	} else {
-		if (pmem[id].cached)
-			pmem[id].vbase = ioremap_cached(pmem[id].base,
-						pmem[id].size);
-	#ifdef ioremap_ext_buffered
-		else if (pmem[id].buffered)
-			pmem[id].vbase = ioremap_ext_buffered(pmem[id].base,
-						pmem[id].size);
-	#endif
-		else
-			pmem[id].vbase = ioremap(pmem[id].base, pmem[id].size);
-	}
-}
-
-int pmem_setup(struct android_pmem_platform_data *pdata,
-	       long (*ioctl)(struct file *, unsigned int, unsigned long),
-	       int (*release)(struct inode *, struct file *))
-{
-	int i, index = 0, id;
-	struct vm_struct *pmem_vma = NULL;
-	struct page *page;
-
-	if (id_count >= PMEM_MAX_DEVICES) {
-		pr_alert("pmem: %s: unable to register driver(%s) - no more "
-			"devices available!\n", __func__, pdata->name);
-		goto err_no_mem;
-	}
-
-	if (!pdata->size) {
-		pr_alert("pmem: %s: unable to register pmem driver(%s) - zero "
-			"size passed in!\n", __func__, pdata->name);
-		goto err_no_mem;
-	}
-
-	id = id_count++;
-
-	pmem[id].id = id;
-
-	if (pmem[id].allocate) {
-		pr_alert("pmem: %s: unable to register pmem driver - "
-			"duplicate registration of %s!\n",
-			__func__, pdata->name);
-		goto err_no_mem;
-	}
-
-	pmem[id].allocator_type = pdata->allocator_type;
-
-	/* 'quantum' is a "hidden" variable that defaults to 0 in the board
-	 * files */
-	pmem[id].quantum = pdata->quantum ?: PMEM_MIN_ALLOC;
-	if (pmem[id].quantum < PMEM_MIN_ALLOC ||
-		!is_power_of_2(pmem[id].quantum)) {
-		pr_alert("pmem: %s: unable to register pmem driver %s - "
-			"invalid quantum value (%#x)!\n",
-			__func__, pdata->name, pmem[id].quantum);
-		goto err_reset_pmem_info;
-	}
-
-	if (pdata->size % pmem[id].quantum) {
-		/* bad alignment for size! */
-		pr_alert("pmem: %s: Unable to register driver %s - "
-			"memory region size (%#lx) is not a multiple of "
-			"quantum size(%#x)!\n", __func__, pdata->name,
-			pdata->size, pmem[id].quantum);
-		goto err_reset_pmem_info;
-	}
-
-	pmem[id].cached = pdata->cached;
-	pmem[id].buffered = pdata->buffered;
-	pmem[id].size = pdata->size;
-	pmem[id].memory_type = pdata->memory_type;
-	strlcpy(pmem[id].name, pdata->name, PMEM_NAME_SIZE);
-
-	pmem[id].num_entries = pmem[id].size / pmem[id].quantum;
-
-	memset(&pmem[id].kobj, 0, sizeof(pmem[0].kobj));
-	pmem[id].kobj.kset = pmem_kset;
-
-	switch (pmem[id].allocator_type) {
-	case PMEM_ALLOCATORTYPE_ALLORNOTHING:
-		pmem[id].allocate = pmem_allocator_all_or_nothing;
-		pmem[id].free = pmem_free_all_or_nothing;
-		pmem[id].free_space = pmem_free_space_all_or_nothing;
-		pmem[id].len = pmem_len_all_or_nothing;
-		pmem[id].start_addr = pmem_start_addr_all_or_nothing;
-		pmem[id].num_entries = 1;
-		pmem[id].quantum = pmem[id].size;
-		pmem[id].allocator.all_or_nothing.allocated = 0;
-
-		if (kobject_init_and_add(&pmem[id].kobj,
-				&pmem_allornothing_ktype, NULL,
-				"%s", pdata->name))
-			goto out_put_kobj;
-
-		break;
-
-	case PMEM_ALLOCATORTYPE_BUDDYBESTFIT:
-		pmem[id].allocator.buddy_bestfit.buddy_bitmap = kmalloc(
-			pmem[id].num_entries * sizeof(struct pmem_bits),
-			GFP_KERNEL);
-		if (!pmem[id].allocator.buddy_bestfit.buddy_bitmap)
-			goto err_reset_pmem_info;
-
-		memset(pmem[id].allocator.buddy_bestfit.buddy_bitmap, 0,
-			sizeof(struct pmem_bits) * pmem[id].num_entries);
-
-		for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--)
-			if ((pmem[id].num_entries) &  1<<i) {
-				PMEM_BUDDY_ORDER(id, index) = i;
-				index = PMEM_BUDDY_NEXT_INDEX(id, index);
-			}
-		pmem[id].allocate = pmem_allocator_buddy_bestfit;
-		pmem[id].free = pmem_free_buddy_bestfit;
-		pmem[id].free_space = pmem_free_space_buddy_bestfit;
-		pmem[id].len = pmem_len_buddy_bestfit;
-		pmem[id].start_addr = pmem_start_addr_buddy_bestfit;
-		if (kobject_init_and_add(&pmem[id].kobj,
-				&pmem_buddy_bestfit_ktype, NULL,
-				"%s", pdata->name))
-			goto out_put_kobj;
-
-		break;
-
-	case PMEM_ALLOCATORTYPE_BITMAP: /* 0, default if not explicit */
-		pmem[id].allocator.bitmap.bitm_alloc = kmalloc(
-			PMEM_INITIAL_NUM_BITMAP_ALLOCATIONS *
-				sizeof(*pmem[id].allocator.bitmap.bitm_alloc),
-			GFP_KERNEL);
-		if (!pmem[id].allocator.bitmap.bitm_alloc) {
-			pr_alert("pmem: %s: Unable to register pmem "
-					"driver %s - can't allocate "
-					"bitm_alloc!\n",
-					__func__, pdata->name);
-			goto err_reset_pmem_info;
-		}
-
-		if (kobject_init_and_add(&pmem[id].kobj,
-				&pmem_bitmap_ktype, NULL,
-				"%s", pdata->name))
-			goto out_put_kobj;
-
-		for (i = 0; i < PMEM_INITIAL_NUM_BITMAP_ALLOCATIONS; i++) {
-			pmem[id].allocator.bitmap.bitm_alloc[i].bit = -1;
-			pmem[id].allocator.bitmap.bitm_alloc[i].quanta = 0;
-		}
-
-		pmem[id].allocator.bitmap.bitmap_allocs =
-			PMEM_INITIAL_NUM_BITMAP_ALLOCATIONS;
-
-		pmem[id].allocator.bitmap.bitmap =
-			kcalloc((pmem[id].num_entries + 31) / 32,
-				sizeof(unsigned int), GFP_KERNEL);
-		if (!pmem[id].allocator.bitmap.bitmap) {
-			pr_alert("pmem: %s: Unable to register pmem "
-				"driver - can't allocate bitmap!\n",
-				__func__);
-			goto err_cant_register_device;
-		}
-		pmem[id].allocator.bitmap.bitmap_free = pmem[id].num_entries;
-
-		pmem[id].allocate = pmem_allocator_bitmap;
-		pmem[id].free = pmem_free_bitmap;
-		pmem[id].free_space = pmem_free_space_bitmap;
-		pmem[id].len = pmem_len_bitmap;
-		pmem[id].start_addr = pmem_start_addr_bitmap;
-
-		DLOG("bitmap allocator id %d (%s), num_entries %u, raw size "
-			"%lu, quanta size %u\n",
-			id, pdata->name, pmem[id].allocator.bitmap.bitmap_free,
-			pmem[id].size, pmem[id].quantum);
-		break;
-
-	case PMEM_ALLOCATORTYPE_SYSTEM:
-
-		INIT_LIST_HEAD(&pmem[id].allocator.system_mem.alist);
-
-		pmem[id].allocator.system_mem.used = 0;
-		pmem[id].vbase = NULL;
-
-		if (kobject_init_and_add(&pmem[id].kobj,
-				&pmem_system_ktype, NULL,
-				"%s", pdata->name))
-			goto out_put_kobj;
-
-		pmem[id].allocate = pmem_allocator_system;
-		pmem[id].free = pmem_free_system;
-		pmem[id].free_space = pmem_free_space_system;
-		pmem[id].len = pmem_len_system;
-		pmem[id].start_addr = pmem_start_addr_system;
-		pmem[id].num_entries = 0;
-		pmem[id].quantum = PAGE_SIZE;
-
-		DLOG("system allocator id %d (%s), raw size %lu\n",
-			id, pdata->name, pmem[id].size);
-		break;
-
-	default:
-		pr_alert("Invalid allocator type (%d) for pmem driver\n",
-			pdata->allocator_type);
-		goto err_reset_pmem_info;
-	}
-
-	pmem[id].ioctl = ioctl;
-	pmem[id].release = release;
-	mutex_init(&pmem[id].arena_mutex);
-	mutex_init(&pmem[id].data_list_mutex);
-	INIT_LIST_HEAD(&pmem[id].data_list);
-
-	pmem[id].dev.name = pdata->name;
-	pmem[id].dev.minor = id;
-	pmem[id].dev.fops = &pmem_fops;
-	pmem[id].reusable = pdata->reusable;
-	pr_info("pmem: Initializing %s as %s\n",
-		pdata->name, pdata->cached ? "cached" : "non-cached");
-
-	if (misc_register(&pmem[id].dev)) {
-		pr_alert("Unable to register pmem driver!\n");
-		goto err_cant_register_device;
-	}
-
-	if (!pmem[id].reusable) {
-		pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
-			pmem[id].memory_type, PAGE_SIZE);
-		if (!pmem[id].base) {
-			pr_err("pmem: Cannot allocate from reserved memory for %s\n",
-				pdata->name);
-			goto err_misc_deregister;
-		}
-	}
-
-	/* reusable pmem requires map on demand */
-	pmem[id].map_on_demand = pdata->map_on_demand || pdata->reusable;
-	if (pmem[id].map_on_demand) {
-		if (pmem[id].reusable) {
-			const struct fmem_data *fmem_info = fmem_get_info();
-			pmem[id].area = fmem_info->area;
-			pmem[id].base = fmem_info->phys;
-		} else {
-			pmem_vma = get_vm_area(pmem[id].size, VM_IOREMAP);
-			if (!pmem_vma) {
-				pr_err("pmem: Failed to allocate virtual space for "
-					"%s\n", pdata->name);
-				goto err_free;
-			}
-			pr_err("pmem: Reserving virtual address range %lx - %lx for"
-				" %s\n", (unsigned long) pmem_vma->addr,
-				(unsigned long) pmem_vma->addr + pmem[id].size,
-				pdata->name);
-			pmem[id].area = pmem_vma;
-		}
-	} else
-		pmem[id].area = NULL;
-
-	page = alloc_page(GFP_KERNEL);
-	if (!page) {
-		pr_err("pmem: Failed to allocate page for %s\n", pdata->name);
-		goto cleanup_vm;
-	}
-	pmem[id].garbage_pfn = page_to_pfn(page);
-	atomic_set(&pmem[id].allocation_cnt, 0);
-
-	if (pdata->setup_region)
-		pmem[id].region_data = pdata->setup_region();
-
-	if (pdata->request_region)
-		pmem[id].mem_request = pdata->request_region;
-
-	if (pdata->release_region)
-		pmem[id].mem_release = pdata->release_region;
-
-	pr_info("allocating %lu bytes at %lx physical for %s\n",
-		pmem[id].size, pmem[id].base, pmem[id].name);
-
-	return 0;
-
-cleanup_vm:
-	if (!pmem[id].reusable)
-		remove_vm_area(pmem_vma);
-err_free:
-	if (!pmem[id].reusable)
-		free_contiguous_memory_by_paddr(pmem[id].base);
-err_misc_deregister:
-	misc_deregister(&pmem[id].dev);
-err_cant_register_device:
-out_put_kobj:
-	kobject_put(&pmem[id].kobj);
-	if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BUDDYBESTFIT)
-		kfree(pmem[id].allocator.buddy_bestfit.buddy_bitmap);
-	else if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BITMAP) {
-		kfree(pmem[id].allocator.bitmap.bitmap);
-		kfree(pmem[id].allocator.bitmap.bitm_alloc);
-	}
-err_reset_pmem_info:
-	pmem[id].allocate = 0;
-	pmem[id].dev.minor = -1;
-err_no_mem:
-	return -1;
-}
-
-static int pmem_probe(struct platform_device *pdev)
-{
-	struct android_pmem_platform_data *pdata;
-
-	if (!pdev || !pdev->dev.platform_data) {
-		pr_alert("Unable to probe pmem!\n");
-		return -1;
-	}
-	pdata = pdev->dev.platform_data;
-
-	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
-
-	return pmem_setup(pdata, NULL, NULL);
-}
-
-static int pmem_remove(struct platform_device *pdev)
-{
-	int id = pdev->id;
-	__free_page(pfn_to_page(pmem[id].garbage_pfn));
-	pm_runtime_disable(&pdev->dev);
-	if (pmem[id].vbase)
-		iounmap(pmem[id].vbase);
-	if (pmem[id].map_on_demand && !pmem[id].reusable && pmem[id].area)
-		free_vm_area(pmem[id].area);
-	if (pmem[id].base)
-		free_contiguous_memory_by_paddr(pmem[id].base);
-	kobject_put(&pmem[id].kobj);
-	if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BUDDYBESTFIT)
-		kfree(pmem[id].allocator.buddy_bestfit.buddy_bitmap);
-	else if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BITMAP) {
-		kfree(pmem[id].allocator.bitmap.bitmap);
-		kfree(pmem[id].allocator.bitmap.bitm_alloc);
-	}
-	misc_deregister(&pmem[id].dev);
-	return 0;
-}
-
-static int pmem_runtime_suspend(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: suspending...\n");
-	return 0;
-}
-
-static int pmem_runtime_resume(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: resuming...\n");
-	return 0;
-}
-
-static const struct dev_pm_ops pmem_dev_pm_ops = {
-	.runtime_suspend = pmem_runtime_suspend,
-	.runtime_resume = pmem_runtime_resume,
-};
-
-static struct platform_driver pmem_driver = {
-	.probe = pmem_probe,
-	.remove = pmem_remove,
-	.driver = { .name = "android_pmem",
-		    .pm = &pmem_dev_pm_ops,
-  }
-};
-
-
-static int __init pmem_init(void)
-{
-	/* create /sys/kernel/<PMEM_SYSFS_DIR_NAME> directory */
-	pmem_kset = kset_create_and_add(PMEM_SYSFS_DIR_NAME,
-		NULL, kernel_kobj);
-	if (!pmem_kset) {
-		pr_err("pmem(%s):kset_create_and_add fail\n", __func__);
-		return -ENOMEM;
-	}
-
-	return platform_driver_register(&pmem_driver);
-}
-
-static void __exit pmem_exit(void)
-{
-	platform_driver_unregister(&pmem_driver);
-}
-
-module_init(pmem_init);
-module_exit(pmem_exit);
-
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index 3c3a62b..726e9a6 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -80,25 +80,22 @@
 };
 
 /**
- * struct ecm_ipa_ctx - saved pointer for the std ecm network device
+ * struct ecm_ipa_ctx - saved pointer for the ecm_ipa network device
  *                which allow ecm_ipa to be a singleton
  */
 static struct ecm_ipa_dev *ecm_ipa_ctx;
 
-static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl);
-static int ecm_ipa_set_device_ethernet_addr(
-	u8 *dev_ethaddr, u8 device_ethaddr[]);
-static void ecm_ipa_packet_receive_notify(void *priv,
-		enum ipa_dp_evt_type evt,
-		unsigned long data);
-static void ecm_ipa_tx_complete_notify(void *priv,
-		enum ipa_dp_evt_type evt,
-		unsigned long data);
-static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl);
 static int ecm_ipa_open(struct net_device *net);
+static void ecm_ipa_packet_receive_notify(void *priv,
+		enum ipa_dp_evt_type evt, unsigned long data);
+static void ecm_ipa_tx_complete_notify(void *priv,
+		enum ipa_dp_evt_type evt, unsigned long data);
 static int ecm_ipa_stop(struct net_device *net);
-static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb,
-					struct net_device *net);
+static int ecm_ipa_rules_cfg(struct ecm_ipa_dev *dev,
+		const void *dst_mac, const void *src_mac);
+static void ecm_ipa_rules_destroy(struct ecm_ipa_dev *dev);
+static int ecm_ipa_register_properties(void);
+static void ecm_ipa_deregister_properties(void);
 static void ecm_ipa_rm_notify(void *user_data, enum ipa_rm_event event,
 		unsigned long data);
 static int ecm_ipa_create_rm_resource(struct ecm_ipa_dev *dev);
@@ -106,25 +103,28 @@
 static bool rx_filter(struct sk_buff *skb);
 static bool tx_filter(struct sk_buff *skb);
 static bool rm_enabled(struct ecm_ipa_dev *dev);
-
-static int ecm_ipa_rules_cfg(struct ecm_ipa_dev *dev,
-		const void *dst_mac, const void *src_mac);
-static int ecm_ipa_register_properties(void);
-static void ecm_ipa_deregister_properties(void);
-static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev);
-static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *dev);
-static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file);
+static int resource_request(struct ecm_ipa_dev *dev);
+static void resource_release(struct ecm_ipa_dev *dev);
+static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb,
+					struct net_device *net);
 static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file);
+static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file,
+		const char __user *buf, size_t count, loff_t *ppos);
+static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file);
+static ssize_t ecm_ipa_debugfs_enable_write(struct file *file,
+		const char __user *buf, size_t count, loff_t *ppos);
 static ssize_t ecm_ipa_debugfs_enable_read(struct file *file,
 		char __user *ubuf, size_t count, loff_t *ppos);
 static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file,
 		char __user *ubuf, size_t count, loff_t *ppos);
-static ssize_t ecm_ipa_debugfs_enable_write(struct file *file,
-		const char __user *buf, size_t count, loff_t *ppos);
-static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file,
-		const char __user *buf, size_t count, loff_t *ppos);
-static void eth_get_drvinfo(struct net_device *net,
-		struct ethtool_drvinfo *drv_info);
+static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev);
+static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *dev);
+static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl);
+static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl);
+static int ecm_ipa_set_device_ethernet_addr(u8 *dev_ethaddr,
+		u8 device_ethaddr[]);
+static int ecm_ipa_init_module(void);
+static void ecm_ipa_cleanup_module(void);
 
 static const struct net_device_ops ecm_ipa_netdev_ops = {
 	.ndo_open		= ecm_ipa_open,
@@ -133,24 +133,352 @@
 	.ndo_set_mac_address = eth_mac_addr,
 };
 
-static const struct ethtool_ops ops = {
-	.get_drvinfo = eth_get_drvinfo,
-	.get_link = ethtool_op_get_link,
-};
-
 const struct file_operations ecm_ipa_debugfs_dma_ops = {
-	.open = ecm_ipa_debugfs_dma_open,
+		.open = ecm_ipa_debugfs_dma_open,
 	.read = ecm_ipa_debugfs_enable_read,
 	.write = ecm_ipa_debugfs_enable_write_dma,
 };
 
 const struct file_operations ecm_ipa_debugfs_atomic_ops = {
-		.open = ecm_ipa_debugfs_atomic_open,
-		.read = ecm_ipa_debugfs_atomic_read,
+	.open = ecm_ipa_debugfs_atomic_open,
+	.read = ecm_ipa_debugfs_atomic_read,
 };
 
 /**
- * ecm_ipa_init() - initializes internal data structures
+ * ecm_ipa_init() - create network device and initializes internal
+ * data structures
+ * @params: in/out parameters required for ecm_ipa initialization
+ *
+ * Shall be called prior to pipe connection.
+ * The out parameters (the callbacks) shall be supplied to ipa_connect.
+ * Detailed description:
+ *  - allocate the network device
+ *  - set default values for driver internals
+ *  - create debugfs folder and files
+ *  - create IPA resource manager client
+ *  - add header insertion rules for IPA driver (based on host/device
+ *    Ethernet addresses given in input params)
+ *  - register tx/rx properties to IPA driver (will be later used
+ *    by IPA configuration manager to configure reset of the IPA rules)
+ *  - set the carrier state to "off" (until ecm_ipa_connect is called)
+ *  - register the network device
+ *  - set the out parameters
+ *
+ * Returns negative errno, or zero on success
+ */
+int ecm_ipa_init(struct ecm_ipa_params *params)
+{
+	int result = 0;
+	struct net_device *net;
+	struct ecm_ipa_dev *dev;
+
+	ECM_IPA_LOG_ENTRY();
+	pr_debug("%s initializing\n", DRIVER_NAME);
+	NULL_CHECK(params);
+
+	pr_debug("host_ethaddr=%pM, device_ethaddr=%pM\n",
+		params->host_ethaddr,
+		params->device_ethaddr);
+
+	net = alloc_etherdev(sizeof(struct ecm_ipa_dev));
+	if (!net) {
+		result = -ENOMEM;
+		ECM_IPA_ERROR("fail to allocate etherdev\n");
+		goto fail_alloc_etherdev;
+	}
+	pr_debug("network device was successfully allocated\n");
+
+	dev = netdev_priv(net);
+	memset(dev, 0, sizeof(*dev));
+	dev->net = net;
+	ecm_ipa_ctx = dev;
+	dev->tx_enable = true;
+	dev->rx_enable = true;
+	dev->rm_enable = true;
+	dev->outstanding_high = DEFAULT_OUTSTANDING_HIGH;
+	dev->outstanding_low = DEFAULT_OUTSTANDING_LOW;
+	atomic_set(&dev->outstanding_pkts, 0);
+	snprintf(net->name, sizeof(net->name), "%s%%d", "ecm");
+	net->netdev_ops = &ecm_ipa_netdev_ops;
+	pr_debug("internal data structures were intialized and defaults set\n");
+
+	result = ecm_ipa_debugfs_init(dev);
+	if (result)
+		goto fail_debugfs;
+	pr_debug("debugfs entries were created\n");
+
+	result = ecm_ipa_create_rm_resource(dev);
+	if (result) {
+		ECM_IPA_ERROR("fail on RM create\n");
+		goto fail_create_rm;
+	}
+	pr_debug("RM resource was created\n");
+
+	result = ecm_ipa_set_device_ethernet_addr(net->dev_addr,
+			params->device_ethaddr);
+	if (result) {
+		ECM_IPA_ERROR("set device MAC failed\n");
+		goto fail_set_device_ethernet;
+	}
+	pr_debug("Device Ethernet address set %pM\n", net->dev_addr);
+
+	result = ecm_ipa_rules_cfg(dev, params->host_ethaddr,
+			params->device_ethaddr);
+	if (result) {
+		ECM_IPA_ERROR("fail on ipa rules set\n");
+		goto fail_rules_cfg;
+	}
+	pr_debug("Ethernet header insertion set\n");
+
+	result = ecm_ipa_register_properties();
+	if (result) {
+		ECM_IPA_ERROR("fail on properties set\n");
+		goto fail_register_tx;
+	}
+	pr_debug("ecm_ipa 2 Tx and 2 Rx properties were registered\n");
+
+	netif_carrier_off(net);
+	pr_debug("set carrier off\n");
+
+	result = register_netdev(net);
+	if (result) {
+		ECM_IPA_ERROR("register_netdev failed: %d\n", result);
+		goto fail_register_netdev;
+	}
+	pr_debug("register_netdev succeeded\n");
+
+	params->ecm_ipa_rx_dp_notify = ecm_ipa_packet_receive_notify;
+	params->ecm_ipa_tx_dp_notify = ecm_ipa_tx_complete_notify;
+	params->private = (void *)dev;
+	ECM_IPA_LOG_EXIT();
+
+	return 0;
+
+fail_register_netdev:
+	ecm_ipa_deregister_properties();
+fail_register_tx:
+	ecm_ipa_rules_destroy(dev);
+fail_set_device_ethernet:
+fail_rules_cfg:
+	ecm_ipa_destory_rm_resource(dev);
+fail_create_rm:
+	ecm_ipa_debugfs_destroy(dev);
+fail_debugfs:
+	free_netdev(net);
+fail_alloc_etherdev:
+	return result;
+}
+EXPORT_SYMBOL(ecm_ipa_init);
+
+
+int ecm_ipa_connect(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl,
+		void *priv)
+{
+	struct ecm_ipa_dev *dev = priv;
+
+	ECM_IPA_LOG_ENTRY();
+	NULL_CHECK(priv);
+	pr_debug("usb_to_ipa_hdl = %d, ipa_to_usb_hdl = %d, priv=0x%p\n",
+					usb_to_ipa_hdl, ipa_to_usb_hdl, priv);
+
+	if (!usb_to_ipa_hdl || usb_to_ipa_hdl >= IPA_CLIENT_MAX) {
+		ECM_IPA_ERROR("usb_to_ipa_hdl(%d) is not a valid ipa handle\n",
+				usb_to_ipa_hdl);
+		return -EINVAL;
+	}
+	if (!ipa_to_usb_hdl || ipa_to_usb_hdl >= IPA_CLIENT_MAX) {
+		ECM_IPA_ERROR("ipa_to_usb_hdl(%d) is not a valid ipa handle\n",
+				ipa_to_usb_hdl);
+		return -EINVAL;
+	}
+	dev->ipa_to_usb_hdl = ipa_to_usb_hdl;
+	dev->usb_to_ipa_hdl = usb_to_ipa_hdl;
+	ecm_ipa_ep_registers_cfg(usb_to_ipa_hdl, ipa_to_usb_hdl);
+	pr_debug("end-point configured\n");
+
+	netif_carrier_on(dev->net);
+	if (!netif_carrier_ok(dev->net)) {
+		ECM_IPA_ERROR("netif_carrier_ok error\n");
+		return -EBUSY;
+	}
+	pr_debug("carrier_on notified, ecm_ipa is operational\n");
+
+	ECM_IPA_LOG_EXIT();
+	return 0;
+}
+EXPORT_SYMBOL(ecm_ipa_connect);
+
+static int ecm_ipa_open(struct net_device *net)
+{
+	struct ecm_ipa_dev *dev;
+	ECM_IPA_LOG_ENTRY();
+
+	dev = netdev_priv(net);
+
+	if (!netif_carrier_ok(net))
+		pr_debug("carrier is not ON yet - continuing\n");
+
+	netif_start_queue(net);
+	pr_debug("queue started\n");
+
+	ECM_IPA_LOG_EXIT();
+	return 0;
+}
+
+/**
+ * ecm_ipa_start_xmit() - send data from APPs to USB core via IPA core
+ * @skb: packet received from Linux stack
+ * @net: the network device being used to send this packet
+ *
+ * Several conditions needed in order to send the packet to IPA:
+ * - we are in a valid state were the queue is not stopped
+ * - Filter Tx switch is turned off
+ * - The resources required for actual Tx are all up
+ *
+ */
+static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb,
+					struct net_device *net)
+{
+	int ret;
+	netdev_tx_t status = NETDEV_TX_BUSY;
+	struct ecm_ipa_dev *dev = netdev_priv(net);
+
+	if (unlikely(netif_queue_stopped(net))) {
+		ECM_IPA_ERROR("interface queue is stopped\n");
+		goto out;
+	}
+
+	if (unlikely(tx_filter(skb))) {
+		dev_kfree_skb_any(skb);
+		pr_debug("packet got filtered out on Tx path\n");
+		status = NETDEV_TX_OK;
+		goto out;
+	}
+	ret = resource_request(dev);
+	if (ret) {
+		pr_debug("Waiting to resource\n");
+		netif_stop_queue(net);
+		goto resource_busy;
+	}
+
+	if (atomic_read(&dev->outstanding_pkts) >= dev->outstanding_high) {
+		pr_debug("Outstanding high boundary reached (%d)- stopping queue\n",
+				dev->outstanding_high);
+		netif_stop_queue(net);
+		status = -NETDEV_TX_BUSY;
+		goto out;
+	}
+
+	ret = ipa_tx_dp(IPA_TO_USB_CLIENT, skb, NULL);
+	if (ret) {
+		ECM_IPA_ERROR("ipa transmit failed (%d)\n", ret);
+		goto fail_tx_packet;
+	}
+
+	atomic_inc(&dev->outstanding_pkts);
+	net->stats.tx_packets++;
+	net->stats.tx_bytes += skb->len;
+	status = NETDEV_TX_OK;
+	goto out;
+
+fail_tx_packet:
+out:
+	resource_release(dev);
+resource_busy:
+	return status;
+}
+
+/**
+ * ecm_ipa_packet_receive_notify() - Rx notify
+ *
+ * @priv: ecm driver context
+ * @evt: event type
+ * @data: data provided with event
+ *
+ * IPA will pass a packet with skb->data pointing to Ethernet packet frame
+ */
+static void ecm_ipa_packet_receive_notify(void *priv,
+		enum ipa_dp_evt_type evt,
+		unsigned long data)
+{
+	struct sk_buff *skb = (struct sk_buff *)data;
+	struct ecm_ipa_dev *dev = priv;
+	int result;
+
+	if (evt != IPA_RECEIVE)	{
+		ECM_IPA_ERROR("A none IPA_RECEIVE event in ecm_ipa_receive\n");
+		return;
+	}
+
+	skb->dev = dev->net;
+	skb->protocol = eth_type_trans(skb, dev->net);
+	if (rx_filter(skb)) {
+		pr_debug("packet got filtered out on Rx path\n");
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	result = netif_rx(skb);
+	if (result)
+		ECM_IPA_ERROR("fail on netif_rx\n");
+	dev->net->stats.rx_packets++;
+	dev->net->stats.rx_bytes += skb->len;
+
+	return;
+}
+
+static int ecm_ipa_stop(struct net_device *net)
+{
+	ECM_IPA_LOG_ENTRY();
+	pr_debug("stopping net device\n");
+	netif_stop_queue(net);
+	ECM_IPA_LOG_EXIT();
+	return 0;
+}
+
+int ecm_ipa_disconnect(void *priv)
+{
+	struct ecm_ipa_dev *dev = priv;
+	ECM_IPA_LOG_ENTRY();
+	NULL_CHECK(dev);
+	pr_debug("priv=0x%p\n", priv);
+	netif_carrier_off(dev->net);
+	ECM_IPA_LOG_EXIT();
+	return 0;
+}
+EXPORT_SYMBOL(ecm_ipa_disconnect);
+
+
+/**
+ * ecm_ipa_cleanup() - destroys all
+ * ecm information
+ * @priv: main driver context parameters
+ *
+ */
+void ecm_ipa_cleanup(void *priv)
+{
+	struct ecm_ipa_dev *dev = priv;
+	ECM_IPA_LOG_ENTRY();
+	pr_debug("priv=0x%p\n", priv);
+	if (!dev) {
+		ECM_IPA_ERROR("dev NULL pointer\n");
+		return;
+	}
+
+	ecm_ipa_destory_rm_resource(dev);
+	ecm_ipa_debugfs_destroy(dev);
+
+	unregister_netdev(dev->net);
+	free_netdev(dev->net);
+
+	pr_debug("cleanup done\n");
+	ecm_ipa_ctx = NULL;
+	ECM_IPA_LOG_EXIT();
+	return ;
+}
+EXPORT_SYMBOL(ecm_ipa_cleanup);
+
+/**
  * @ecm_ipa_rx_dp_notify: supplied callback to be called by the IPA
  * driver upon data packets received from USB pipe into IPA core.
  * @ecm_ipa_rt_dp_notify: supplied callback to be called by the IPA
@@ -167,54 +495,7 @@
  *
  * Returns negative errno, or zero on success
  */
-int ecm_ipa_init(ecm_ipa_callback *ecm_ipa_rx_dp_notify,
-		ecm_ipa_callback *ecm_ipa_tx_dp_notify,
-		void **priv)
-{
-	int ret = 0;
-	struct net_device *net;
-	struct ecm_ipa_dev *dev;
-	ECM_IPA_LOG_ENTRY();
-	pr_debug("%s initializing\n", DRIVER_NAME);
-	NULL_CHECK(ecm_ipa_rx_dp_notify);
-	NULL_CHECK(ecm_ipa_tx_dp_notify);
-	NULL_CHECK(priv);
-	pr_debug("rx_cb=0x%p, tx_cb=0x%p priv=0x%p\n",
-			ecm_ipa_rx_dp_notify, ecm_ipa_tx_dp_notify, *priv);
-	net = alloc_etherdev(sizeof(struct ecm_ipa_dev));
-	if (!net) {
-		ret = -ENOMEM;
-		ECM_IPA_ERROR("fail to allocate etherdev\n");
-		goto fail_alloc_etherdev;
-	}
-	pr_debug("etherdev was successfully allocated\n");
-	dev = netdev_priv(net);
-	memset(dev, 0, sizeof(*dev));
-	dev->tx_enable = true;
-	dev->rx_enable = true;
-	atomic_set(&dev->outstanding_pkts, 0);
-	dev->outstanding_high = DEFAULT_OUTSTANDING_HIGH;
-	dev->outstanding_low = DEFAULT_OUTSTANDING_LOW;
-	dev->net = net;
-	ecm_ipa_ctx = dev;
-	*priv = (void *)dev;
-	snprintf(net->name, sizeof(net->name), "%s%%d", "ecm");
-	net->netdev_ops = &ecm_ipa_netdev_ops;
-	pr_debug("internal data structures were intialized\n");
-	ret = ecm_ipa_debugfs_init(dev);
-	if (ret)
-		goto fail_debugfs;
-	pr_debug("debugfs entries were created\n");
-	*ecm_ipa_rx_dp_notify = ecm_ipa_packet_receive_notify;
-	*ecm_ipa_tx_dp_notify = ecm_ipa_tx_complete_notify;
-	ECM_IPA_LOG_EXIT();
-	return 0;
-fail_debugfs:
-	free_netdev(net);
-fail_alloc_etherdev:
-	return ret;
-}
-EXPORT_SYMBOL(ecm_ipa_init);
+
 
 /**
  * ecm_ipa_rules_cfg() - set header insertion and register Tx/Rx properties
@@ -390,106 +671,6 @@
  *
  * Returns negative errno, or zero on success
  */
-int ecm_ipa_configure(u8 host_ethaddr[], u8 device_ethaddr[],
-		void *priv)
-{
-	struct ecm_ipa_dev *dev = priv;
-	struct net_device *net;
-	int result;
-	ECM_IPA_LOG_ENTRY();
-	NULL_CHECK(host_ethaddr);
-	NULL_CHECK(host_ethaddr);
-	NULL_CHECK(dev);
-	net = dev->net;
-	NULL_CHECK(net);
-	pr_debug("priv=0x%p, host_ethaddr=%pM device_ethaddr=%pM\n",
-					priv, host_ethaddr, device_ethaddr);
-	result = ecm_ipa_create_rm_resource(dev);
-	if (result) {
-		ECM_IPA_ERROR("fail on RM create\n");
-		return -EINVAL;
-	}
-	pr_debug("RM resource was created\n");
-	netif_carrier_off(dev->net);
-	result = ecm_ipa_set_device_ethernet_addr(net->dev_addr,
-			device_ethaddr);
-	if (result) {
-		ECM_IPA_ERROR("set device MAC failed\n");
-		goto fail_set_device_ethernet;
-	}
-	result = ecm_ipa_rules_cfg(dev, host_ethaddr, device_ethaddr);
-	if (result) {
-		ECM_IPA_ERROR("fail on ipa rules set\n");
-		goto fail_set_device_ethernet;
-	}
-	pr_debug("Ethernet header insertion was set\n");
-	result = ecm_ipa_register_properties();
-	if (result) {
-		ECM_IPA_ERROR("fail on properties set\n");
-		goto fail_register_tx;
-	}
-	pr_debug("ECM 2 Tx and 2 Rx properties were registered\n");
-	result = register_netdev(net);
-	if (result) {
-		ECM_IPA_ERROR("register_netdev failed: %d\n", result);
-		goto fail_register_netdev;
-	}
-	pr_debug("register_netdev succeeded\n");
-	ECM_IPA_LOG_EXIT();
-	return 0;
-fail_register_netdev:
-	ecm_ipa_deregister_properties();
-fail_register_tx:
-fail_set_device_ethernet:
-	ecm_ipa_rules_destroy(dev);
-	ecm_ipa_destory_rm_resource(dev);
-	free_netdev(net);
-	return result;
-}
-EXPORT_SYMBOL(ecm_ipa_configure);
-
-int ecm_ipa_connect(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl,
-		void *priv)
-{
-	struct ecm_ipa_dev *dev = priv;
-	ECM_IPA_LOG_ENTRY();
-	NULL_CHECK(priv);
-	pr_debug("usb_to_ipa_hdl = %d, ipa_to_usb_hdl = %d, priv=0x%p\n",
-					usb_to_ipa_hdl, ipa_to_usb_hdl, priv);
-	if (!usb_to_ipa_hdl || usb_to_ipa_hdl >= IPA_CLIENT_MAX) {
-		ECM_IPA_ERROR("usb_to_ipa_hdl(%d) is not a valid ipa handle\n",
-				usb_to_ipa_hdl);
-		return -EINVAL;
-	}
-	if (!ipa_to_usb_hdl || ipa_to_usb_hdl >= IPA_CLIENT_MAX) {
-		ECM_IPA_ERROR("ipa_to_usb_hdl(%d) is not a valid ipa handle\n",
-				ipa_to_usb_hdl);
-		return -EINVAL;
-	}
-	dev->ipa_to_usb_hdl = ipa_to_usb_hdl;
-	dev->usb_to_ipa_hdl = usb_to_ipa_hdl;
-	ecm_ipa_ep_registers_cfg(usb_to_ipa_hdl, ipa_to_usb_hdl);
-	netif_carrier_on(dev->net);
-	if (!netif_carrier_ok(dev->net)) {
-		ECM_IPA_ERROR("netif_carrier_ok error\n");
-		return -EBUSY;
-	}
-	ECM_IPA_LOG_EXIT();
-	return 0;
-}
-EXPORT_SYMBOL(ecm_ipa_connect);
-
-int ecm_ipa_disconnect(void *priv)
-{
-	struct ecm_ipa_dev *dev = priv;
-	ECM_IPA_LOG_ENTRY();
-	NULL_CHECK(dev);
-	pr_debug("priv=0x%p\n", priv);
-	netif_carrier_off(dev->net);
-	ECM_IPA_LOG_EXIT();
-	return 0;
-}
-EXPORT_SYMBOL(ecm_ipa_disconnect);
 
 
 static void ecm_ipa_rm_notify(void *user_data, enum ipa_rm_event event,
@@ -551,12 +732,18 @@
 
 static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *dev)
 {
+	int result;
+
 	ECM_IPA_LOG_ENTRY();
+
 	if (!dev->rm_enable)
 		return;
 	ipa_rm_delete_dependency(IPA_RM_RESOURCE_STD_ECM_PROD,
 			IPA_RM_RESOURCE_USB_CONS);
 	ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_STD_ECM_PROD);
+	result = ipa_rm_delete_resource(IPA_RM_RESOURCE_STD_ECM_PROD);
+	if (result)
+		ECM_IPA_ERROR("resource deletion failed\n");
 
 	ECM_IPA_LOG_EXIT();
 }
@@ -578,52 +765,6 @@
 	return dev->rm_enable;
 }
 
-static int ecm_ipa_open(struct net_device *net)
-{
-	ECM_IPA_LOG_ENTRY();
-	netif_start_queue(net);
-	ECM_IPA_LOG_EXIT();
-	return 0;
-}
-
-static int ecm_ipa_stop(struct net_device *net)
-{
-	ECM_IPA_LOG_ENTRY();
-	pr_debug("stopping net device\n");
-	netif_stop_queue(net);
-	ECM_IPA_LOG_EXIT();
-	return 0;
-}
-
-/**
- * ecm_ipa_cleanup() - destroys all
- * ecm information
- * @priv: main driver context parameters
- *
- */
-void ecm_ipa_cleanup(void *priv)
-{
-	struct ecm_ipa_dev *dev = priv;
-	ECM_IPA_LOG_ENTRY();
-	pr_debug("priv=0x%p\n", priv);
-	if (!dev) {
-		ECM_IPA_ERROR("dev NULL pointer\n");
-		return;
-	}
-
-	ecm_ipa_destory_rm_resource(dev);
-	ecm_ipa_debugfs_destroy(dev);
-
-	unregister_netdev(dev->net);
-	free_netdev(dev->net);
-
-	pr_debug("cleanup done\n");
-	ecm_ipa_ctx = NULL;
-	ECM_IPA_LOG_EXIT();
-	return ;
-}
-EXPORT_SYMBOL(ecm_ipa_cleanup);
-
 static int resource_request(struct ecm_ipa_dev *dev)
 {
 	int result = 0;
@@ -646,108 +787,6 @@
 }
 
 /**
- * ecm_ipa_start_xmit() - send data from APPs to USB core via IPA core
- * @skb: packet received from Linux stack
- * @net: the network device being used to send this packet
- *
- * Several conditions needed in order to send the packet to IPA:
- * - we are in a valid state were the queue is not stopped
- * - Filter Tx switch is turned off
- * - The resources required for actual Tx are all up
- *
- */
-static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb,
-					struct net_device *net)
-{
-	int ret;
-	netdev_tx_t status = NETDEV_TX_BUSY;
-	struct ecm_ipa_dev *dev = netdev_priv(net);
-
-	if (unlikely(netif_queue_stopped(net))) {
-		ECM_IPA_ERROR("interface queue is stopped\n");
-		goto out;
-	}
-
-	if (unlikely(tx_filter(skb))) {
-		dev_kfree_skb_any(skb);
-		pr_debug("packet got filtered out on Tx path\n");
-		status = NETDEV_TX_OK;
-		goto out;
-	}
-	ret = resource_request(dev);
-	if (ret) {
-		pr_debug("Waiting to resource\n");
-		netif_stop_queue(net);
-		goto resource_busy;
-	}
-
-	if (atomic_read(&dev->outstanding_pkts) >= dev->outstanding_high) {
-		pr_debug("Outstanding high boundary reached (%d)- stopping queue\n",
-				dev->outstanding_high);
-		netif_stop_queue(net);
-		status = -NETDEV_TX_BUSY;
-		goto out;
-	}
-
-	ret = ipa_tx_dp(IPA_TO_USB_CLIENT, skb, NULL);
-	if (ret) {
-		ECM_IPA_ERROR("ipa transmit failed (%d)\n", ret);
-		goto fail_tx_packet;
-	}
-
-	atomic_inc(&dev->outstanding_pkts);
-	net->stats.tx_packets++;
-	net->stats.tx_bytes += skb->len;
-	status = NETDEV_TX_OK;
-	goto out;
-
-fail_tx_packet:
-out:
-	resource_release(dev);
-resource_busy:
-	return status;
-}
-
-/**
- * ecm_ipa_packet_receive_notify() - Rx notify
- *
- * @priv: ecm driver context
- * @evt: event type
- * @data: data provided with event
- *
- * IPA will pass a packet with skb->data pointing to Ethernet packet frame
- */
-void ecm_ipa_packet_receive_notify(void *priv,
-		enum ipa_dp_evt_type evt,
-		unsigned long data)
-{
-	struct sk_buff *skb = (struct sk_buff *)data;
-	struct ecm_ipa_dev *dev = priv;
-	int result;
-
-	if (evt != IPA_RECEIVE)	{
-		ECM_IPA_ERROR("A none IPA_RECEIVE event in ecm_ipa_receive\n");
-		return;
-	}
-
-	skb->dev = dev->net;
-	skb->protocol = eth_type_trans(skb, dev->net);
-	if (rx_filter(skb)) {
-		pr_debug("packet got filtered out on Rx path\n");
-		dev_kfree_skb_any(skb);
-		return;
-	}
-
-	result = netif_rx(skb);
-	if (result)
-		ECM_IPA_ERROR("fail on netif_rx\n");
-	dev->net->stats.rx_packets++;
-	dev->net->stats.rx_bytes += skb->len;
-
-	return;
-}
-
-/**
  * ecm_ipa_tx_complete_notify() - Rx notify
  *
  * @priv: ecm driver context
@@ -757,7 +796,7 @@
  * Check that the packet is the one we sent and release it
  * This function will be called in defered context in IPA wq.
  */
-void ecm_ipa_tx_complete_notify(void *priv,
+static void ecm_ipa_tx_complete_notify(void *priv,
 		enum ipa_dp_evt_type evt,
 		unsigned long data)
 {
@@ -948,15 +987,6 @@
 	debugfs_remove_recursive(dev->directory);
 }
 
-static void eth_get_drvinfo(struct net_device *net,
-		struct ethtool_drvinfo *drv_info)
-{
-	ECM_IPA_LOG_ENTRY();
-	strlcpy(drv_info->driver, DRIVER_NAME, sizeof(drv_info->driver));
-	ECM_IPA_LOG_EXIT();
-}
-
-
 /**
  * ecm_ipa_ep_cfg() - configure the USB endpoints for ECM
  *
@@ -972,7 +1002,7 @@
  *  - No aggregation
  *  - Add Ethernet header
  */
-int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl)
+static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl)
 {
 	int result = 0;
 	struct ipa_ep_cfg usb_to_ipa_ep_cfg;
@@ -1014,7 +1044,7 @@
  * which is needed for cores that does not support blocks logic
  * Note that client handles are the actual pipe index
  */
-int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl)
+static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl)
 {
 	int result = 0;
 	struct ipa_ep_cfg_mode cfg_mode;
@@ -1050,7 +1080,8 @@
  *
  * Returns 0 for success, negative otherwise
  */
-int ecm_ipa_set_device_ethernet_addr(u8 *dev_ethaddr, u8 device_ethaddr[])
+static int ecm_ipa_set_device_ethernet_addr(u8 *dev_ethaddr,
+		u8 device_ethaddr[])
 {
 	if (!is_valid_ether_addr(device_ethaddr))
 		return -EINVAL;
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index bbf9719..26353ec 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -86,8 +86,10 @@
 	struct list_head bam_tx_pool;
 	spinlock_t bam_tx_pool_spinlock;
 	struct workqueue_struct *a2_mux_tx_workqueue;
+	struct workqueue_struct *a2_mux_rx_workqueue;
 	int a2_mux_initialized;
 	bool bam_is_connected;
+	bool bam_connect_in_progress;
 	int a2_mux_send_power_vote_on_init_once;
 	int a2_mux_sw_bridge_is_connected;
 	u32 a2_device_handle;
@@ -237,7 +239,6 @@
 		INIT_COMPLETION(a2_mux_ctx->ul_wakeup_ack_completion);
 		power_vote(0);
 	}
-	a2_mux_ctx->bam_is_connected = false;
 }
 
 static void ul_wakeup(void)
@@ -245,7 +246,8 @@
 	int ret;
 
 	mutex_lock(&a2_mux_ctx->wakeup_lock);
-	if (a2_mux_ctx->bam_is_connected) {
+	if (a2_mux_ctx->bam_is_connected &&
+				!a2_mux_ctx->bam_connect_in_progress) {
 		IPADBG("%s Already awake\n", __func__);
 		mutex_unlock(&a2_mux_ctx->wakeup_lock);
 		return;
@@ -259,7 +261,6 @@
 			grab_wakelock();
 		else
 			a2_mux_ctx->a2_pc_disabled_wakelock_skipped = 1;
-		a2_mux_ctx->bam_is_connected = true;
 		mutex_unlock(&a2_mux_ctx->wakeup_lock);
 		return;
 	}
@@ -298,7 +299,6 @@
 			goto bail;
 		}
 	}
-	a2_mux_ctx->bam_is_connected = true;
 	IPADBG("%s complete\n", __func__);
 	mutex_unlock(&a2_mux_ctx->wakeup_lock);
 	return;
@@ -367,26 +367,82 @@
 		dev_kfree_skb_any(skb);
 }
 
+static bool msm_bam_dmux_kickoff_ul_power_down(void)
+
+{
+	bool is_connected;
+
+	write_lock(&a2_mux_ctx->ul_wakeup_lock);
+	if (a2_mux_ctx->bam_connect_in_progress) {
+		a2_mux_ctx->bam_is_connected = false;
+		is_connected = true;
+	} else {
+		is_connected = a2_mux_ctx->bam_is_connected;
+		a2_mux_ctx->bam_is_connected = false;
+		if (is_connected) {
+			a2_mux_ctx->bam_connect_in_progress = true;
+			queue_work(a2_mux_ctx->a2_mux_tx_workqueue,
+				&a2_mux_ctx->kickoff_ul_power_down);
+		}
+	}
+	write_unlock(&a2_mux_ctx->ul_wakeup_lock);
+	return is_connected;
+}
+
+static bool msm_bam_dmux_kickoff_ul_wakeup(void)
+{
+	bool is_connected;
+
+	write_lock(&a2_mux_ctx->ul_wakeup_lock);
+	if (a2_mux_ctx->bam_connect_in_progress) {
+		a2_mux_ctx->bam_is_connected = true;
+		is_connected = false;
+	} else {
+		is_connected = a2_mux_ctx->bam_is_connected;
+		a2_mux_ctx->bam_is_connected = true;
+		if (!is_connected) {
+			a2_mux_ctx->bam_connect_in_progress = true;
+			queue_work(a2_mux_ctx->a2_mux_tx_workqueue,
+				&a2_mux_ctx->kickoff_ul_wakeup);
+		}
+	}
+	write_unlock(&a2_mux_ctx->ul_wakeup_lock);
+	return is_connected;
+}
+
 static void kickoff_ul_power_down_func(struct work_struct *work)
 {
-	unsigned long flags;
+	bool is_connected;
 
-	write_lock_irqsave(&a2_mux_ctx->ul_wakeup_lock, flags);
-	if (a2_mux_ctx->bam_is_connected) {
-		IPADBG("%s: UL active - forcing powerdown\n", __func__);
-		ul_powerdown();
-	}
-	write_unlock_irqrestore(&a2_mux_ctx->ul_wakeup_lock, flags);
-	ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
-			IPA_RM_RESOURCE_A2_CONS);
+	IPADBG("%s: UL active - forcing powerdown\n", __func__);
+	ul_powerdown();
+	write_lock(&a2_mux_ctx->ul_wakeup_lock);
+	is_connected = a2_mux_ctx->bam_is_connected;
+	a2_mux_ctx->bam_is_connected = false;
+	a2_mux_ctx->bam_connect_in_progress = false;
+	write_unlock(&a2_mux_ctx->ul_wakeup_lock);
+	if (is_connected)
+		msm_bam_dmux_kickoff_ul_wakeup();
+	else
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+						IPA_RM_RESOURCE_A2_CONS);
 }
 
 static void kickoff_ul_wakeup_func(struct work_struct *work)
 {
-	if (!a2_mux_ctx->bam_is_connected)
-		ul_wakeup();
-	ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+	bool is_connected;
+
+	ul_wakeup();
+	write_lock(&a2_mux_ctx->ul_wakeup_lock);
+	is_connected = a2_mux_ctx->bam_is_connected;
+	a2_mux_ctx->bam_is_connected = true;
+	a2_mux_ctx->bam_connect_in_progress = false;
+	write_unlock(&a2_mux_ctx->ul_wakeup_lock);
+	if (is_connected)
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
 			IPA_RM_RESOURCE_A2_CONS);
+	else
+		msm_bam_dmux_kickoff_ul_power_down();
 }
 
 static void kickoff_ul_request_resource_func(struct work_struct *work)
@@ -414,33 +470,6 @@
 	toggle_apps_ack();
 }
 
-static bool msm_bam_dmux_kickoff_ul_wakeup(void)
-{
-	bool is_connected;
-
-	read_lock(&a2_mux_ctx->ul_wakeup_lock);
-	is_connected = a2_mux_ctx->bam_is_connected;
-	read_unlock(&a2_mux_ctx->ul_wakeup_lock);
-	if (!is_connected)
-		queue_work(a2_mux_ctx->a2_mux_tx_workqueue,
-			   &a2_mux_ctx->kickoff_ul_wakeup);
-	return is_connected;
-}
-
-static bool msm_bam_dmux_kickoff_ul_power_down(void)
-
-{
-	bool is_connected;
-
-	read_lock(&a2_mux_ctx->ul_wakeup_lock);
-	is_connected = a2_mux_ctx->bam_is_connected;
-	read_unlock(&a2_mux_ctx->ul_wakeup_lock);
-	if (is_connected)
-		queue_work(a2_mux_ctx->a2_mux_tx_workqueue,
-			   &a2_mux_ctx->kickoff_ul_power_down);
-	return is_connected;
-}
-
 static void ipa_embedded_notify(void *priv,
 				enum ipa_dp_evt_type evt,
 				unsigned long data)
@@ -631,7 +660,7 @@
 		IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_on_reqs_in);
 		grab_wakelock();
 		(void) connect_to_bam();
-		queue_work(a2_mux_ctx->a2_mux_tx_workqueue,
+		queue_work(a2_mux_ctx->a2_mux_rx_workqueue,
 			   &a2_mux_ctx->kickoff_ul_request_resource);
 	} else if (!(new_state & SMSM_A2_POWER_CONTROL)) {
 		IPADBG("%s: MODEM PWR CTRL 0\n", __func__);
@@ -926,7 +955,8 @@
 	}
 	spin_unlock_irqrestore(&a2_mux_ctx->bam_ch[id].lock, flags);
 	read_lock(&a2_mux_ctx->ul_wakeup_lock);
-	is_connected = a2_mux_ctx->bam_is_connected;
+	is_connected = a2_mux_ctx->bam_is_connected &&
+					!a2_mux_ctx->bam_connect_in_progress;
 	read_unlock(&a2_mux_ctx->ul_wakeup_lock);
 	if (!is_connected)
 		return -ENODEV;
@@ -1230,7 +1260,8 @@
 	a2_mux_ctx->bam_ch[lcid].use_wm = 0;
 	spin_unlock_irqrestore(&a2_mux_ctx->bam_ch[lcid].lock, flags);
 	read_lock(&a2_mux_ctx->ul_wakeup_lock);
-	is_connected = a2_mux_ctx->bam_is_connected;
+	is_connected = a2_mux_ctx->bam_is_connected &&
+					!a2_mux_ctx->bam_connect_in_progress;
 	read_unlock(&a2_mux_ctx->ul_wakeup_lock);
 	if (!is_connected)
 		return -ENODEV;
@@ -1299,7 +1330,8 @@
 	if (!a2_mux_ctx->a2_mux_initialized)
 		return -ENODEV;
 	read_lock(&a2_mux_ctx->ul_wakeup_lock);
-	is_connected = a2_mux_ctx->bam_is_connected;
+	is_connected = a2_mux_ctx->bam_is_connected &&
+					!a2_mux_ctx->bam_connect_in_progress;
 	read_unlock(&a2_mux_ctx->ul_wakeup_lock);
 	if (!is_connected && !bam_ch_is_in_reset(lcid))
 		return -ENODEV;
@@ -1446,6 +1478,13 @@
 		       __func__);
 		return -ENOMEM;
 	}
+	a2_mux_ctx->a2_mux_rx_workqueue =
+		create_singlethread_workqueue("a2_mux_rx");
+	if (!a2_mux_ctx->a2_mux_rx_workqueue) {
+		IPAERR("%s: a2_mux_rx_workqueue alloc failed\n",
+			__func__);
+		return -ENOMEM;
+	}
 	return 0;
 }
 
@@ -1571,5 +1610,7 @@
 				NULL);
 	if (a2_mux_ctx->a2_mux_tx_workqueue)
 		destroy_workqueue(a2_mux_ctx->a2_mux_tx_workqueue);
+	if (a2_mux_ctx->a2_mux_rx_workqueue)
+		destroy_workqueue(a2_mux_ctx->a2_mux_rx_workqueue);
 	return 0;
 }
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index a78879d..a95eafe 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -15,18 +15,14 @@
 
 static void ipa_enable_data_path(u32 clnt_hdl)
 {
-	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
-
 	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
 		/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
 		return;
 	}
 
-	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && ep->suspended) {
+	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1)
 		ipa_write_reg(ipa_ctx->mmio,
 				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 0);
-		ep->suspended = false;
-	}
 }
 
 static int ipa_disable_data_path(u32 clnt_hdl)
@@ -50,7 +46,7 @@
 		goto fail_alloc;
 	}
 
-	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && !ep->suspended) {
+	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1) {
 		ipa_write_reg(ipa_ctx->mmio,
 				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
 
@@ -85,7 +81,6 @@
 				ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
 				ep->cfg.aggr.aggr_time_limit)
 			msleep(ep->cfg.aggr.aggr_time_limit);
-		ep->suspended = true;
 	}
 
 	return 0;
@@ -298,7 +293,9 @@
 	if (in->client == IPA_CLIENT_HSIC1_CONS ||
 			in->client == IPA_CLIENT_HSIC2_CONS ||
 			in->client == IPA_CLIENT_HSIC3_CONS ||
-			in->client == IPA_CLIENT_HSIC4_CONS) {
+			in->client == IPA_CLIENT_HSIC4_CONS ||
+			in->client == IPA_CLIENT_A2_TETHERED_CONS ||
+			in->client == IPA_CLIENT_A2_EMBEDDED_CONS) {
 		IPADBG("disable holb for ep=%d tmr=%d\n", ipa_ep_idx,
 			ipa_ctx->hol_timer);
 		ipa_write_reg(ipa_ctx->mmio,
@@ -367,6 +364,11 @@
 
 	ep = &ipa_ctx->ep[clnt_hdl];
 
+	if (ep->suspended) {
+		ipa_inc_client_enable_clks();
+		ep->suspended = false;
+	}
+
 	result = ipa_disable_data_path(clnt_hdl);
 	if (result) {
 		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
@@ -422,55 +424,79 @@
 EXPORT_SYMBOL(ipa_disconnect);
 
 /**
- * ipa_connection_suspend() - suspend B2B connection to/from IPA
+ * ipa_resume() - low-level IPA client resume
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
  *
- * Should be called by the driver of the peripheral that wants to suspend
- * its BAM-BAM connection to/from IPA in BAM-BAM mode. The pipe is not
- * disconnected and must later be resumed before data transfer can begin
+ * Should be called by the driver of the peripheral that wants to resume IPA
+ * connection. Resume IPA connection results in turning on IPA clocks in
+ * case they were off as a result of suspend.
+ * this api can be called only if a call to ipa_suspend() was
+ * made.
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa_connection_suspend(u32 clnt_hdl)
+int ipa_resume(u32 clnt_hdl)
 {
-	int result;
+	struct ipa_ep_context *ep;
 
 	if (clnt_hdl >= IPA_NUM_PIPES || ipa_ctx->ep[clnt_hdl].valid == 0) {
-		IPAERR("bad parm.\n");
-		return -EINVAL;
-	}
-	result = ipa_disable_data_path(clnt_hdl);
-	if (result)
-		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
-				clnt_hdl);
-
-	return result;
-}
-EXPORT_SYMBOL(ipa_connection_suspend);
-
-/**
- * ipa_connection_resume() - resume B2B connection to/from IPA
- * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
- *
- * Should be called by the driver of the peripheral that wants to resume
- * its previously suspended BAM-BAM connection to/from IPA in BAM-BAM mode.
- *
- * Returns:	0 on success, negative on failure
- *
- * Note:	Should not be called from atomic context
- */
-int ipa_connection_resume(u32 clnt_hdl)
-{
-	if (clnt_hdl >= IPA_NUM_PIPES || ipa_ctx->ep[clnt_hdl].valid == 0) {
-		IPAERR("bad parm.\n");
+		IPAERR("bad parm. clnt_hdl %d\n", clnt_hdl);
 		return -EINVAL;
 	}
 
-	ipa_enable_data_path(clnt_hdl);
+	ep = &ipa_ctx->ep[clnt_hdl];
+
+	if (!ep->suspended) {
+		IPAERR("EP not suspended. clnt_hdl %d\n", clnt_hdl);
+		return -EPERM;
+	}
+
+	ipa_inc_client_enable_clks();
+	ep->suspended = false;
 
 	return 0;
 }
-EXPORT_SYMBOL(ipa_connection_resume);
+EXPORT_SYMBOL(ipa_resume);
 
+/**
+* ipa_suspend() - low-level IPA client suspend
+* @clnt_hdl:	[in] opaque client handle assigned by IPA to client
+*
+* Should be called by the driver of the peripheral that wants to suspend IPA
+* connection. Suspend IPA connection results in turning off IPA clocks in
+* case that there is no active clients using IPA. Pipes remains connected in
+* case of suspend.
+*
+* Returns:	0 on success, negative on failure
+*
+* Note:	Should not be called from atomic context
+*/
+int ipa_suspend(u32 clnt_hdl)
+{
+	struct ipa_ep_context *ep;
+
+	if (clnt_hdl >= IPA_NUM_PIPES || ipa_ctx->ep[clnt_hdl].valid == 0) {
+		IPAERR("bad parm. clnt_hdl %d\n", clnt_hdl);
+		return -EINVAL;
+	}
+
+	ep = &ipa_ctx->ep[clnt_hdl];
+
+	if (ep->suspended) {
+		IPAERR("EP already suspended. clnt_hdl %d\n", clnt_hdl);
+		return -EPERM;
+	}
+
+	if (IPA_CLIENT_IS_CONS(ep->client) &&
+				ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
+				ep->cfg.aggr.aggr_time_limit)
+		msleep(ep->cfg.aggr.aggr_time_limit);
+
+	ipa_dec_client_disable_clks();
+	ep->suspended = true;
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_suspend);
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index c28a5ee..9062ab8 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -1410,19 +1410,38 @@
 		goto bail;
 	}
 
-	/* Request the BRIDGE_PROD resource */
+	/*
+	 * Delete part of IPA resource manager dependency graph. Only the
+	 * BRIDGE_PROD <-> A2 dependency remains intact
+	 */
+	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
+				       IPA_RM_RESOURCE_USB_CONS);
+	if ((res != 0) && (res != -EINPROGRESS))
+		TETH_ERR(
+			"Failed deleting ipa_rm dependency BRIDGE_PROD <-> USB_CONS\n");
+	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
+				       IPA_RM_RESOURCE_A2_CONS);
+	if ((res != 0) && (res != -EINPROGRESS))
+		TETH_ERR(
+			"Failed deleting ipa_rm dependency USB_PROD <-> A2_CONS\n");
+	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_A2_PROD,
+				       IPA_RM_RESOURCE_USB_CONS);
+	if ((res != 0) && (res != -EINPROGRESS))
+		TETH_ERR(
+			"Failed deleting ipa_rm dependency A2_PROD <-> USB_CONS\n");
+
+	/* Request the BRIDGE_PROD resource, A2 and IPA should power up */
 	res = teth_request_resource();
 	if (res) {
 		TETH_ERR("request_resource() failed.\n");
 		goto bail;
 	}
 
-	teth_ctx->is_connected = false;
-
 	/* Close the channel to A2 */
 	if (a2_mux_close_channel(A2_MUX_TETHERED_0))
 		TETH_ERR("a2_mux_close_channel() failed\n");
 
+	/* Teardown the IPA HW bridge */
 	if (teth_ctx->is_hw_bridge_complete) {
 		/* Delete header entries */
 		if (ipa_del_hdr(teth_ctx->hdr_del))
@@ -1452,27 +1471,14 @@
 
 	ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_BRIDGE_PROD);
 
-	/* Delete IPA Resource manager dependency graph */
-	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
-				       IPA_RM_RESOURCE_USB_CONS);
-	if ((res != 0) && (res != -EINPROGRESS))
-		TETH_ERR(
-			"Failed deleting ipa_rm dependency BRIDGE_PROD <-> USB_CONS\n");
+	/* Delete the last ipa_rm dependency - BRIDGE_PROD <-> A2 */
 	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
 				       IPA_RM_RESOURCE_A2_CONS);
 	if ((res != 0) && (res != -EINPROGRESS))
 		TETH_ERR(
 			"Failed deleting ipa_rm dependency BRIDGE_PROD <-> A2_CONS\n");
-	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
-				       IPA_RM_RESOURCE_A2_CONS);
-	if ((res != 0) && (res != -EINPROGRESS))
-		TETH_ERR(
-			"Failed deleting ipa_rm dependency USB_PROD <-> A2_CONS\n");
-	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_A2_PROD,
-				       IPA_RM_RESOURCE_USB_CONS);
-	if ((res != 0) && (res != -EINPROGRESS))
-		TETH_ERR(
-			"Failed deleting ipa_rm dependency A2_PROD <-> USB_CONS\n");
+
+	teth_ctx->is_connected = false;
 bail:
 	TETH_DBG_FUNC_EXIT();
 
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index fd42c47..866b921 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -375,7 +375,7 @@
 
 #define CC_READING_RESOLUTION_N	542535
 #define CC_READING_RESOLUTION_D	100000
-static int cc_reading_to_uv(int16_t reading)
+static s64 cc_reading_to_uv(s64 reading)
 {
 	return div_s64(reading * CC_READING_RESOLUTION_N,
 					CC_READING_RESOLUTION_D);
@@ -582,7 +582,7 @@
 	return false;
 }
 
-static bool is_batfet_open(struct qpnp_bms_chip *chip)
+static bool is_battery_full(struct qpnp_bms_chip *chip)
 {
 	union power_supply_propval ret = {0,};
 
@@ -610,18 +610,32 @@
 
 	iadc_channel = chip->use_external_rsense ?
 				EXTERNAL_RSENSE : INTERNAL_RSENSE;
-	rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
-				VBAT_SNS, &v_result);
-	if (rc) {
-		pr_err("vadc read failed with rc: %d\n", rc);
-		return rc;
+	if (is_battery_full(chip)) {
+		rc = get_battery_current(chip, ibat_ua);
+		if (rc) {
+			pr_err("bms current read failed with rc: %d\n", rc);
+			return rc;
+		}
+		rc = qpnp_vadc_read(VBAT_SNS, &v_result);
+		if (rc) {
+			pr_err("vadc read failed with rc: %d\n", rc);
+			return rc;
+		}
+		*vbat_uv = (int)v_result.physical;
+	} else {
+		rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
+					VBAT_SNS, &v_result);
+		if (rc) {
+			pr_err("adc sync read failed with rc: %d\n", rc);
+			return rc;
+		}
+		/*
+		* reverse the current read by the iadc, since the bms uses
+		* flipped battery current polarity.
+		*/
+		*ibat_ua = -1 * (int)i_result.result_ua;
+		*vbat_uv = (int)v_result.physical;
 	}
-	/*
-	 * reverse the current read by the iadc, since the bms uses
-	 * flipped battery current polarity.
-	 */
-	*ibat_ua = -1 * (int)i_result.result_ua;
-	*vbat_uv = (int)v_result.physical;
 
 	return 0;
 }
@@ -774,14 +788,6 @@
 	return (fcc_uah * pc) / 100;
 }
 
-#define CC_RESOLUTION_N		542535
-#define CC_RESOLUTION_D		100000
-
-static s64 cc_to_uv(s64 cc)
-{
-	return div_s64(cc * CC_RESOLUTION_N, CC_RESOLUTION_D);
-}
-
 #define CC_READING_TICKS	56
 #define SLEEP_CLK_HZ		32764
 #define SECONDS_PER_HOUR	3600
@@ -817,7 +823,7 @@
 
 	qpnp_iadc_get_gain_and_offset(&calibration);
 	pr_debug("cc = %lld\n", cc);
-	cc_voltage_uv = cc_to_uv(cc);
+	cc_voltage_uv = cc_reading_to_uv(cc);
 	cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
 					calibration.gain_raw
 					- calibration.offset_raw);
@@ -1409,7 +1415,7 @@
 		goto out;
 	}
 
-	if (ibat_ua < 0 && !is_batfet_open(chip)) {
+	if (ibat_ua < 0 && !is_battery_full(chip)) {
 		soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
 				batt_temp);
 		goto out;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 14a42dd..993b2cb 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -2123,9 +2123,10 @@
 		}
 		INIT_WORK(&chip->adc_measure_work,
 			qpnp_bat_if_adc_measure_work);
-		INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
 	}
 
+	INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
+
 	if (chip->dc_chgpth_base) {
 		chip->dc_psy.name = "qpnp-dc";
 		chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
@@ -2248,7 +2249,7 @@
 	return rc;
 }
 
-static const struct dev_pm_ops qpnp_bms_pm_ops = {
+static const struct dev_pm_ops qpnp_chg_pm_ops = {
 	.resume		= qpnp_chg_resume,
 	.suspend	= qpnp_chg_suspend,
 };
@@ -2257,9 +2258,10 @@
 	.probe		= qpnp_charger_probe,
 	.remove		= __devexit_p(qpnp_charger_remove),
 	.driver		= {
-		.name	= QPNP_CHARGER_DEV_NAME,
-		.owner  = THIS_MODULE,
-		.of_match_table = qpnp_charger_match_table,
+		.name		= QPNP_CHARGER_DEV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= qpnp_charger_match_table,
+		.pm		= &qpnp_chg_pm_ops,
 	},
 };
 
diff --git a/drivers/power/smb350_charger.c b/drivers/power/smb350_charger.c
index 21d7aea..11fff43 100644
--- a/drivers/power/smb350_charger.c
+++ b/drivers/power/smb350_charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -263,6 +263,9 @@
 
 	if (!chg_enabled) {
 		pr_warn("Charging not enabled.\n");
+		/* release the wake-lock when DC power removed */
+		if (wake_lock_active(&dev->chg_wake_lock))
+			wake_unlock(&dev->chg_wake_lock);
 		return POWER_SUPPLY_CHARGE_TYPE_NONE;
 	}
 
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 2b9af47..814817b 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -1466,17 +1466,18 @@
 		if (ret)
 			goto read_node_fail;
 
-		key = "qcom,min-level";
-		ret = of_property_read_u32(child_node, key,
-				&rails[i].min_level);
-		if (ret)
-			goto read_node_fail;
-
 		key = "qcom,freq-req";
 		rails[i].freq_req = of_property_read_bool(child_node, key);
+		if (rails[i].freq_req)
+			rails[i].min_level = MSM_CPUFREQ_NO_LIMIT;
+		else {
+			key = "qcom,min-level";
+			ret = of_property_read_u32(child_node, key,
+				&rails[i].min_level);
+			if (ret)
+				goto read_node_fail;
+		}
 
-		if (ret)
-			goto read_node_fail;
 		rails[i].curr_level = 0;
 		rails[i].reg = NULL;
 		i++;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index ede2ef1..1d02e32 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -110,6 +110,34 @@
 		wake_up_interruptible(&vt_event_waitqueue);
 }
 
+static void __vt_event_queue(struct vt_event_wait *vw)
+{
+	unsigned long flags;
+	/* Prepare the event */
+	INIT_LIST_HEAD(&vw->list);
+	vw->done = 0;
+	/* Queue our event */
+	spin_lock_irqsave(&vt_event_lock, flags);
+	list_add(&vw->list, &vt_events);
+	spin_unlock_irqrestore(&vt_event_lock, flags);
+}
+
+static void __vt_event_wait(struct vt_event_wait *vw)
+{
+	/* Wait for it to pass */
+	wait_event_interruptible(vt_event_waitqueue, vw->done);
+}
+
+static void __vt_event_dequeue(struct vt_event_wait *vw)
+{
+	unsigned long flags;
+
+	/* Dequeue it */
+	spin_lock_irqsave(&vt_event_lock, flags);
+	list_del(&vw->list);
+	spin_unlock_irqrestore(&vt_event_lock, flags);
+}
+
 /**
  *	vt_event_wait		-	wait for an event
  *	@vw: our event
@@ -121,20 +149,9 @@
 
 static void vt_event_wait(struct vt_event_wait *vw)
 {
-	unsigned long flags;
-	/* Prepare the event */
-	INIT_LIST_HEAD(&vw->list);
-	vw->done = 0;
-	/* Queue our event */
-	spin_lock_irqsave(&vt_event_lock, flags);
-	list_add(&vw->list, &vt_events);
-	spin_unlock_irqrestore(&vt_event_lock, flags);
-	/* Wait for it to pass */
-	wait_event_interruptible(vt_event_waitqueue, vw->done);
-	/* Dequeue it */
-	spin_lock_irqsave(&vt_event_lock, flags);
-	list_del(&vw->list);
-	spin_unlock_irqrestore(&vt_event_lock, flags);
+	__vt_event_queue(vw);
+	__vt_event_wait(vw);
+	__vt_event_dequeue(vw);
 }
 
 /**
@@ -177,10 +194,14 @@
 {
 	struct vt_event_wait vw;
 	do {
-		if (n == fg_console + 1)
-			break;
 		vw.event.event = VT_EVENT_SWITCH;
-		vt_event_wait(&vw);
+		__vt_event_queue(&vw);
+		if (n == fg_console + 1) {
+			__vt_event_dequeue(&vw);
+			break;
+		}
+		__vt_event_wait(&vw);
+		__vt_event_dequeue(&vw);
 		if (vw.done == 0)
 			return -EINTR;
 	} while (vw.event.newev != n);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 147e3db..bc1fa07 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -426,6 +426,7 @@
 struct adb_data {
 	bool opened;
 	bool enabled;
+	struct android_dev *dev;
 };
 
 static int
@@ -459,6 +460,7 @@
 
 	data->enabled = true;
 
+
 	/* Disable the gadget until adbd is ready */
 	if (!data->opened)
 		android_disable(dev);
@@ -490,27 +492,45 @@
 	struct android_dev *dev = adb_function.android_dev;
 	struct adb_data *data = adb_function.config;
 
+	/* dev is null in case ADB is not in the composition */
+	if (dev)
+		mutex_lock(&dev->mutex);
+
+	/* Save dev in case the adb function will get disabled */
+	data->dev = dev;
 	data->opened = true;
 
-	if (data->enabled && dev) {
-		mutex_lock(&dev->mutex);
+	if (data->enabled && dev)
 		android_enable(dev);
+
+	if (dev)
 		mutex_unlock(&dev->mutex);
-	}
 }
 
 static void adb_closed_callback(void)
 {
-	struct android_dev *dev = adb_function.android_dev;
 	struct adb_data *data = adb_function.config;
+	struct android_dev *dev = adb_function.android_dev;
+
+	/* In case new composition is without ADB, use saved one */
+	if (!dev)
+		dev = data->dev;
+
+	if (!dev)
+		pr_err("adb_closed_callback: data->dev is NULL");
+
+	if (dev)
+		mutex_lock(&dev->mutex);
 
 	data->opened = false;
 
-	if (data->enabled) {
-		mutex_lock(&dev->mutex);
+	if (data->enabled)
 		android_disable(dev);
+
+	data->dev = NULL;
+
+	if (dev)
 		mutex_unlock(&dev->mutex);
-	}
 }
 
 
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 8e7cbb2..a395d15 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -77,15 +77,7 @@
 	bool				is_open;
 };
 
-struct f_ecm_qc_ipa_params {
-	u8			dev_mac[ETH_ALEN];
-	u8			host_mac[ETH_ALEN];
-	ecm_ipa_callback	ipa_rx_cb;
-	ecm_ipa_callback	ipa_tx_cb;
-	void			*ipa_priv;
-};
-
-static struct f_ecm_qc_ipa_params ipa_params;
+static struct ecm_ipa_params ipa_params;
 
 static inline struct f_ecm_qc *func_to_ecm_qc(struct usb_function *f)
 {
@@ -435,17 +427,17 @@
 
 void *ecm_qc_get_ipa_rx_cb(void)
 {
-	return ipa_params.ipa_rx_cb;
+	return ipa_params.ecm_ipa_rx_dp_notify;
 }
 
 void *ecm_qc_get_ipa_tx_cb(void)
 {
-	return ipa_params.ipa_tx_cb;
+	return ipa_params.ecm_ipa_tx_dp_notify;
 }
 
 void *ecm_qc_get_ipa_priv(void)
 {
-	return ipa_params.ipa_priv;
+	return ipa_params.private;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -849,7 +841,7 @@
 	ecm_qc_string_defs[1].s = NULL;
 
 	if (ecm->xport == USB_GADGET_XPORT_BAM2BAM_IPA)
-		ecm_ipa_cleanup(ipa_params.ipa_priv);
+		ecm_ipa_cleanup(ipa_params.private);
 
 	kfree(ecm);
 }
@@ -920,12 +912,13 @@
 
 	/* export host's Ethernet address in CDC format */
 	if (ecm->xport == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		gether_qc_get_macs(ipa_params.dev_mac, ipa_params.host_mac);
+		gether_qc_get_macs(ipa_params.device_ethaddr,
+				ipa_params.host_ethaddr);
 		snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
 		"%02X%02X%02X%02X%02X%02X",
-		ipa_params.host_mac[0], ipa_params.host_mac[1],
-		ipa_params.host_mac[2], ipa_params.host_mac[3],
-		ipa_params.host_mac[4], ipa_params.host_mac[5]);
+		ipa_params.host_ethaddr[0], ipa_params.host_ethaddr[1],
+		ipa_params.host_ethaddr[2], ipa_params.host_ethaddr[3],
+		ipa_params.host_ethaddr[4], ipa_params.host_ethaddr[5]);
 	} else
 		snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
 		"%02X%02X%02X%02X%02X%02X",
@@ -957,21 +950,15 @@
 	if (ecm->xport != USB_GADGET_XPORT_BAM2BAM_IPA)
 		return status;
 
-	status = ecm_ipa_init(&ipa_params.ipa_rx_cb, &ipa_params.ipa_tx_cb,
-			&ipa_params.ipa_priv);
+	pr_debug("setting ecm_ipa, host_ethaddr=%pM, device_ethaddr=%pM",
+			ipa_params.host_ethaddr, ipa_params.device_ethaddr);
+	status = ecm_ipa_init(&ipa_params);
 	if (status) {
-		pr_err("failed to initialize ECM IPA Driver");
+		pr_err("failed to initialize ecm_ipa");
 		ecm_qc_string_defs[1].s = NULL;
 		kfree(ecm);
-		return status;
-	}
-
-	status = ecm_ipa_configure(ipa_params.host_mac, ipa_params.dev_mac,
-			ipa_params.ipa_priv);
-	if (status) {
-		pr_err("failed to configure ECM IPA Driver");
-		ecm_qc_string_defs[1].s = NULL;
-		kfree(ecm);
+	} else {
+		pr_debug("ecm_ipa successful created");
 	}
 
 	return status;
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 52243eb..f672bd4 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -708,45 +708,6 @@
 		return xres * bpp;
 }
 
-/*
- * physical contiguous memory should be allocated in mdss_fb, and SMMU
- * virtual address mapping can be done in the MDP h/w specific code.   It
- * should have a reference count, if none is current mapped, the SMMU context
- * can bedetached, thus allowing power saving in SMMU.
- */
-static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
-{
-	int dom;
-	void *virt = NULL;
-	unsigned long phys = 0;
-	size_t size;
-	u32 yres = mfd->fbi->var.yres_virtual;
-
-	size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
-
-	if (mfd->index == 0) {
-		virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
-		if (!virt) {
-			pr_err("unable to alloc fbmem size=%u\n", size);
-			return -ENOMEM;
-		}
-		phys = memory_pool_node_paddr(virt);
-		dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
-		msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
-					&mfd->iova);
-
-		pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
-			size, virt, phys, mfd->index);
-	} else {
-		size = 0;
-	}
-
-	mfd->fbi->screen_base = virt;
-	mfd->fbi->fix.smem_start = phys;
-	mfd->fbi->fix.smem_len = size;
-	return 0;
-}
-
 struct mdp3_dma *mdp3_get_dma_pipe(int capability)
 {
 	int i;
@@ -775,12 +736,19 @@
 	return NULL;
 }
 
+static int mdp3_fb_mem_get_iommu_domain(void)
+{
+	if (!mdp3_res)
+		return -ENODEV;
+	return mdp3_res->domains[MDP3_IOMMU_DOMAIN].domain_idx;
+}
+
 static int mdp3_probe(struct platform_device *pdev)
 {
 	int rc;
 	static struct msm_mdp_interface mdp3_interface = {
 	.init_fnc = mdp3_init,
-	.fb_mem_alloc_fnc = mdp3_fbmem_alloc,
+	.fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain,
 	.fb_stride = mdp3_fb_stride,
 	};
 
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 72ad67e..28f61f9 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -42,9 +42,13 @@
 #include <linux/sync.h>
 #include <linux/sw_sync.h>
 #include <linux/file.h>
+#include <linux/memory_alloc.h>
 
 #include <mach/board.h>
 #include <mach/memory.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/msm_memtypes.h>
 
 #include "mdss_fb.h"
 
@@ -652,6 +656,11 @@
 	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 
+	if (!start) {
+		pr_warn("No framebuffer memory is allocated.\n");
+		return -ENOMEM;
+	}
+
 	mdss_fb_pan_idle(mfd);
 	if (off >= len) {
 		/* memory mapped io */
@@ -709,13 +718,68 @@
 	.fb_mmap = mdss_fb_mmap,
 };
 
+static int mdss_fb_alloc_fbmem_iommu(struct msm_fb_data_type *mfd, int dom)
+{
+	void *virt = NULL;
+	unsigned long phys = 0;
+	size_t size = 0;
+	struct platform_device *pdev = mfd->pdev;
+
+	if (!pdev || !pdev->dev.of_node) {
+		pr_err("Invalid device node\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(pdev->dev.of_node,
+				 "qcom,memory-reservation-size",
+				 &size) || !size) {
+		mfd->fbi->screen_base = NULL;
+		mfd->fbi->fix.smem_start = 0;
+		mfd->fbi->fix.smem_len = 0;
+		return 0;
+	}
+
+	pr_info("%s frame buffer reserve_size=0x%x\n", __func__, size);
+
+	if (size < PAGE_ALIGN(mfd->fbi->fix.line_length *
+			      mfd->fbi->var.yres_virtual))
+		pr_warn("reserve size is smaller than framebuffer size\n");
+
+	virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+	if (!virt) {
+		pr_err("unable to alloc fbmem size=%u\n", size);
+		return -ENOMEM;
+	}
+
+	phys = memory_pool_node_paddr(virt);
+
+	msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
+					    &mfd->iova);
+	pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
+		 size, virt, phys, mfd->index);
+
+	mfd->fbi->screen_base = virt;
+	mfd->fbi->fix.smem_start = phys;
+	mfd->fbi->fix.smem_len = size;
+
+	return 0;
+}
+
 static int mdss_fb_alloc_fbmem(struct msm_fb_data_type *mfd)
 {
-	if (!mfd->mdp.fb_mem_alloc_fnc) {
+
+	if (mfd->mdp.fb_mem_alloc_fnc)
+		return mfd->mdp.fb_mem_alloc_fnc(mfd);
+	else if (mfd->mdp.fb_mem_get_iommu_domain) {
+		int dom = mfd->mdp.fb_mem_get_iommu_domain();
+		if (dom >= 0)
+			return mdss_fb_alloc_fbmem_iommu(mfd, dom);
+		else
+			return -ENOMEM;
+	} else {
 		pr_err("no fb memory allocator function defined\n");
 		return -ENOMEM;
 	}
-	return mfd->mdp.fb_mem_alloc_fnc(mfd);
 }
 
 static int mdss_fb_register(struct msm_fb_data_type *mfd)
@@ -1534,12 +1598,15 @@
 static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			 unsigned long arg)
 {
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct msm_fb_data_type *mfd;
 	void __user *argp = (void __user *)arg;
 	struct mdp_page_protection fb_page_protection;
 	int ret = -ENOSYS;
 	struct mdp_buf_sync buf_sync;
 
+	if (!info || !info->par)
+		return -EINVAL;
+	mfd = (struct msm_fb_data_type *)info->par;
 	mdss_fb_power_setting_idle(mfd);
 
 	mdss_fb_pan_idle(mfd);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 6f6f490..5682f0b 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -56,6 +56,7 @@
 
 struct msm_mdp_interface {
 	int (*fb_mem_alloc_fnc)(struct msm_fb_data_type *mfd);
+	int (*fb_mem_get_iommu_domain)(void);
 	int (*init_fnc)(struct msm_fb_data_type *mfd);
 	int (*on_fnc)(struct msm_fb_data_type *mfd);
 	int (*off_fnc)(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_mhl.h b/drivers/video/msm/mdss/mdss_hdmi_mhl.h
index 8fef63e..8a9d4fc 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_mhl.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_mhl.h
@@ -19,9 +19,9 @@
 struct msm_hdmi_mhl_ops {
 	u8 (*tmds_enabled)(struct platform_device *pdev);
 	int (*set_mhl_max_pclk)(struct platform_device *pdev, u32 max_val);
+	int (*set_upstream_hpd)(struct platform_device *pdev, uint8_t on);
 };
 
 int msm_hdmi_register_mhl(struct platform_device *pdev,
-			  struct msm_hdmi_mhl_ops *ops);
-
+			  struct msm_hdmi_mhl_ops *ops, void *data);
 #endif /* __MDSS_HDMI_MHL_H__ */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index dc51b1b..42cc356 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -81,6 +81,7 @@
 	struct hdmi_tx_audio_acr lut[AUDIO_SAMPLE_RATE_MAX];
 };
 
+static int hdmi_tx_set_mhl_hpd(struct platform_device *pdev, uint8_t on);
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
@@ -1950,7 +1951,7 @@
 }
 
 int msm_hdmi_register_mhl(struct platform_device *pdev,
-		struct msm_hdmi_mhl_ops *ops)
+			  struct msm_hdmi_mhl_ops *ops, void *data)
 {
 	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
 
@@ -1966,6 +1967,8 @@
 
 	ops->tmds_enabled = hdmi_tx_tmds_enabled;
 	ops->set_mhl_max_pclk = hdmi_tx_set_mhl_max_pclk;
+	ops->set_upstream_hpd = hdmi_tx_set_mhl_hpd;
+
 	return 0;
 }
 
@@ -2331,6 +2334,9 @@
 		return;
 	}
 
+	/* finish the ongoing hpd work if any */
+	flush_work_sync(&hdmi_ctrl->hpd_int_work);
+
 	/* Turn off HPD interrupts */
 	DSS_REG_W(io, HDMI_HPD_INT_CTRL, 0);
 
@@ -2438,6 +2444,41 @@
 	return rc;
 } /* hdmi_tx_sysfs_enable_hpd */
 
+static int hdmi_tx_set_mhl_hpd(struct platform_device *pdev, uint8_t on)
+{
+	int rc = 0;
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+	hdmi_ctrl = platform_get_drvdata(pdev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!on && hdmi_ctrl->hpd_feature_on) {
+		rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
+	} else if (on && !hdmi_ctrl->hpd_feature_on) {
+		rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+	} else {
+		DEV_DBG("%s: hpd is already '%s'. return\n", __func__,
+			hdmi_ctrl->hpd_feature_on ? "enabled" : "disabled");
+		return rc;
+	}
+
+	if (!rc) {
+		hdmi_ctrl->hpd_feature_on =
+			(~hdmi_ctrl->hpd_feature_on) & BIT(0);
+		DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_feature_on);
+	} else {
+		DEV_ERR("%s: failed to '%s' hpd. rc = %d\n", __func__,
+			on ? "enable" : "disable", rc);
+	}
+
+	return rc;
+
+}
+
 static irqreturn_t hdmi_tx_isr(int irq, void *data)
 {
 	struct dss_io_data *io = NULL;
@@ -2868,7 +2909,7 @@
 
 	switch (module_type) {
 	case HDMI_TX_HPD_PM:
-		mp->num_clk = 2;
+		mp->num_clk = 3;
 		mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
 			mp->num_clk, GFP_KERNEL);
 		if (!mp->clk_config) {
@@ -2884,6 +2925,16 @@
 		snprintf(mp->clk_config[1].clk_name, 32, "%s", "core_clk");
 		mp->clk_config[1].type = DSS_CLK_OTHER;
 		mp->clk_config[1].rate = 19200000;
+
+		/*
+		 * This clock is required to clock MDSS interrupt registers
+		 * when HDMI is the only block turned on within MDSS. Since
+		 * rate for this clock is controlled by MDP driver, treat this
+		 * similar to AHB clock and do not set rate for it.
+		 */
+		snprintf(mp->clk_config[2].clk_name, 32, "%s", "mdp_core_clk");
+		mp->clk_config[2].type = DSS_CLK_AHB;
+		mp->clk_config[2].rate = 0;
 		break;
 
 	case HDMI_TX_CORE_PM:
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index b9457be..772545f 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -55,9 +55,15 @@
 #include "mdss_debug.h"
 
 struct mdss_data_type *mdss_res;
+
+static int mdss_fb_mem_get_iommu_domain(void)
+{
+	return mdss_get_iommu_domain(MDSS_IOMMU_DOMAIN_UNSECURE);
+}
+
 struct msm_mdp_interface mdp5 = {
 	.init_fnc = mdss_mdp_overlay_init,
-	.fb_mem_alloc_fnc = mdss_mdp_alloc_fb_mem,
+	.fb_mem_get_iommu_domain = mdss_fb_mem_get_iommu_domain,
 	.panel_register_done = mdss_panel_register_done,
 	.fb_stride = mdss_mdp_fb_stride,
 };
@@ -136,39 +142,6 @@
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
 static int mdss_mdp_parse_dt_ad_cfg(struct platform_device *pdev);
 
-int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd)
-{
-	int dom;
-	void *virt = NULL;
-	unsigned long phys = 0;
-	size_t size;
-	u32 yres = mfd->fbi->var.yres_virtual;
-
-	size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
-
-	if (mfd->index == 0) {
-		virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
-		if (!virt) {
-			pr_err("unable to alloc fbmem size=%u\n", size);
-			return -ENOMEM;
-		}
-		phys = memory_pool_node_paddr(virt);
-		dom = mdss_get_iommu_domain(MDSS_IOMMU_DOMAIN_UNSECURE);
-		msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
-					&mfd->iova);
-
-		pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
-			size, virt, phys, mfd->index);
-	} else
-		size = 0;
-
-	mfd->fbi->screen_base = virt;
-	mfd->fbi->fix.smem_start = phys;
-	mfd->fbi->fix.smem_len = size;
-
-	return 0;
-}
-
 u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
 {
 	/* The adreno GPU hardware requires that the pitch be aligned to
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 249f89b..a650522 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -110,8 +110,8 @@
 typedef void (*mdp_vsync_handler_t)(struct mdss_mdp_ctl *, ktime_t);
 
 struct mdss_mdp_vsync_handler {
+	bool enabled;
 	mdp_vsync_handler_t vsync_handler;
-	u32 ref_cnt;
 	struct list_head list;
 };
 
@@ -533,7 +533,6 @@
 int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
 
 int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id);
-int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd);
 u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp);
 
 int mdss_panel_register_done(struct mdss_panel_data *pdata);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 638c73f..72cbed9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -203,13 +203,13 @@
 }
 
 
-static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl)
+static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
 {
 	struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
 
 	if (atomic_inc_return(&ctx->vsync_ref) == 1)
 		mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
-	else
+	else if (clear)
 		mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
 				ctl->intf_num);
 }
@@ -227,9 +227,8 @@
 {
 	struct mdss_mdp_video_ctx *ctx;
 	unsigned long flags;
-	struct mdss_mdp_vsync_handler *tmp;
-	bool exist = false;
 	int ret = 0;
+	bool irq_en = false;
 
 	if (!handle || !(handle->vsync_handler)) {
 		ret = -EINVAL;
@@ -244,32 +243,24 @@
 	}
 
 	spin_lock_irqsave(&ctx->vsync_lock, flags);
-	list_for_each_entry(tmp, &(ctx->vsync_handlers), list) {
-		if (tmp->vsync_handler == handle->vsync_handler) {
-			exist = true;
-			tmp->ref_cnt++;
-		}
-	}
-	if (!exist) {
-		handle->ref_cnt = 1;
+	if (!handle->enabled) {
+		handle->enabled = true;
 		list_add(&handle->list, &ctx->vsync_handlers);
+		irq_en = true;
 	}
-
-	video_vsync_irq_enable(ctl);
 	spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+	if (irq_en)
+		video_vsync_irq_enable(ctl, false);
 exit:
 	return ret;
 }
 
-/* passing NULL as handle or vsync_handler will clear all handlers */
 static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
 		struct mdss_mdp_vsync_handler *handle)
 {
 	struct mdss_mdp_video_ctx *ctx;
 	unsigned long flags;
-	struct mdss_mdp_vsync_handler *tmp, *q;
-	bool exist = true;
-	bool used = false;
+	bool irq_dis = false;
 
 	ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
 	if (!ctx) {
@@ -278,26 +269,21 @@
 	}
 
 	spin_lock_irqsave(&ctx->vsync_lock, flags);
-	list_for_each_entry_safe(tmp, q, &ctx->vsync_handlers, list) {
-		if (handle && handle->vsync_handler)
-			exist = (tmp->vsync_handler == handle->vsync_handler);
-		if (exist) {
-			tmp->ref_cnt--;
-			if (handle && handle->vsync_handler)
-				used = (tmp->ref_cnt != 0);
-			if (!used) {
-				video_vsync_irq_disable(ctl);
-				list_del_init(&tmp->list);
-			}
-		}
+	if (handle->enabled) {
+		handle->enabled = false;
+		list_del_init(&handle->list);
+		irq_dis = true;
 	}
 	spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+	if (irq_dis)
+		video_vsync_irq_disable(ctl);
 	return 0;
 }
 
 static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
 {
 	struct mdss_mdp_video_ctx *ctx;
+	struct mdss_mdp_vsync_handler *tmp, *handle;
 	int rc;
 
 	pr_debug("stop ctl=%d\n", ctl->num);
@@ -328,7 +314,8 @@
 			ctl->intf_num);
 	}
 
-	mdss_mdp_video_remove_vsync_handler(ctl, NULL);
+	list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
+		mdss_mdp_video_remove_vsync_handler(ctl, handle);
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   NULL, NULL);
@@ -470,7 +457,7 @@
 
 	if (!ctx->wait_pending) {
 		ctx->wait_pending++;
-		video_vsync_irq_enable(ctl);
+		video_vsync_irq_enable(ctl, true);
 		INIT_COMPLETION(ctx->vsync_comp);
 	} else {
 		WARN(1, "commit without wait! ctl=%d", ctl->num);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index ac1c4ce..56fd163 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1111,7 +1111,8 @@
 
 	fbi = mfd->fbi;
 
-	if (fbi->fix.smem_len == 0 || mdp5_data->borderfill_enable) {
+	if (!fbi->fix.smem_start || fbi->fix.smem_len == 0 ||
+	     mdp5_data->borderfill_enable) {
 		mfd->mdp.kickoff_fnc(mfd);
 		return;
 	}
@@ -1142,9 +1143,13 @@
 		goto pan_display_error;
 	}
 
-	if (is_mdss_iommu_attached())
+	if (is_mdss_iommu_attached()) {
+		if (!mfd->iova) {
+			pr_err("mfd iova is zero\n");
+			goto pan_display_error;
+		}
 		data.p[0].addr = mfd->iova;
-	else
+	} else
 		data.p[0].addr = fbi->fix.smem_start;
 
 	data.p[0].addr += offset;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 12ff943..4e7cc37 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -178,11 +178,9 @@
 	struct mdp_dither_cfg_data dither_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_gamut_cfg_data gamut_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE];
-	struct pp_hist_col_info
-		*hist_col[MDSS_BLOCK_DISP_NUM][MDSS_MDP_MAX_DSPP];
 	u32 hist_data[MDSS_BLOCK_DISP_NUM][HIST_V_SIZE];
 	/* physical info */
-	struct pp_sts_type pp_dspp_sts[MDSS_MDP_MAX_DSPP];
+	struct pp_sts_type pp_disp_sts[MDSS_BLOCK_DISP_NUM];
 	struct pp_hist_col_info dspp_hist[MDSS_MDP_MAX_DSPP];
 };
 
@@ -671,7 +669,7 @@
 			else
 				scale_config |= /* RGB, A */
 					(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
-					(MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+					(MDSS_MDP_SCALE_FILTER_PCMN << 18);
 		}
 
 		phasey_step = mdss_mdp_scale_phase_step(
@@ -728,7 +726,7 @@
 			else
 				scale_config |= /* RGB, A */
 					(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
-					(MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+					(MDSS_MDP_SCALE_FILTER_PCMN << 16);
 		}
 
 		phasex_step = mdss_mdp_scale_phase_step(
@@ -838,7 +836,7 @@
 	else
 		flags = 0;
 
-	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
+	pp_sts = &mdss_pp_res->pp_disp_sts[disp_num];
 	/* GC_LUT is in layer mixer */
 	if (flags & PP_FLAGS_DIRTY_ARGC) {
 		pgc_config = &mdss_pp_res->argc_disp_cfg[disp_num];
@@ -982,7 +980,7 @@
 		goto dspp_exit;
 	ret = 0;
 
-	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
+	pp_sts = &mdss_pp_res->pp_disp_sts[disp_num];
 
 	pp_pa_config(flags, base + MDSS_MDP_REG_DSPP_PA_BASE, pp_sts,
 					&mdss_pp_res->pa_disp_cfg[disp_num]);
@@ -1126,19 +1124,20 @@
  * Set dirty and write bits on features that were enabled so they will be
  * reconfigured
  */
-int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 mixer_num)
+int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num)
 {
-	u32 flags = 0;
+	u32 flags = 0, disp_num;
 	struct pp_sts_type pp_sts;
 	struct mdss_ad_info *ad;
 	struct mdss_data_type *mdata = ctl->mdata;
-	if (mixer_num >= MDSS_MDP_MAX_DSPP) {
-		pr_warn("invalid mixer_num");
+	if (dspp_num >= MDSS_MDP_MAX_DSPP) {
+		pr_warn("invalid dspp_num");
 		return -EINVAL;
 	}
+	disp_num = ctl->mfd->index;
 
-	if (mixer_num < mdata->nad_cfgs) {
-		ad = &mdata->ad_cfgs[mixer_num];
+	if (dspp_num < mdata->nad_cfgs) {
+		ad = &mdata->ad_cfgs[dspp_num];
 
 		if (PP_AD_STATE_CFG & ad->state)
 			pp_ad_cfg_write(ad);
@@ -1150,66 +1149,66 @@
 			ctl->add_vsync_handler(ctl, &ad->handle);
 	}
 
-	pp_sts = mdss_pp_res->pp_dspp_sts[mixer_num];
+	pp_sts = mdss_pp_res->pp_disp_sts[disp_num];
 
 	if (pp_sts.pa_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_PA;
-		if (!(mdss_pp_res->pa_disp_cfg[mixer_num].flags
+		if (!(mdss_pp_res->pa_disp_cfg[disp_num].flags
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->pa_disp_cfg[mixer_num].flags |=
+			mdss_pp_res->pa_disp_cfg[disp_num].flags |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.pcc_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_PCC;
-		if (!(mdss_pp_res->pcc_disp_cfg[mixer_num].ops
+		if (!(mdss_pp_res->pcc_disp_cfg[disp_num].ops
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->pcc_disp_cfg[mixer_num].ops |=
+			mdss_pp_res->pcc_disp_cfg[disp_num].ops |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.igc_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_IGC;
-		if (!(mdss_pp_res->igc_disp_cfg[mixer_num].ops
+		if (!(mdss_pp_res->igc_disp_cfg[disp_num].ops
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->igc_disp_cfg[mixer_num].ops |=
+			mdss_pp_res->igc_disp_cfg[disp_num].ops |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.argc_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_ARGC;
-		if (!(mdss_pp_res->argc_disp_cfg[mixer_num].flags
+		if (!(mdss_pp_res->argc_disp_cfg[disp_num].flags
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->argc_disp_cfg[mixer_num].flags |=
+			mdss_pp_res->argc_disp_cfg[disp_num].flags |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.enhist_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_ENHIST;
-		if (!(mdss_pp_res->enhist_disp_cfg[mixer_num].ops
+		if (!(mdss_pp_res->enhist_disp_cfg[disp_num].ops
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->enhist_disp_cfg[mixer_num].ops |=
+			mdss_pp_res->enhist_disp_cfg[disp_num].ops |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.dither_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_DITHER;
-		if (!(mdss_pp_res->dither_disp_cfg[mixer_num].flags
+		if (!(mdss_pp_res->dither_disp_cfg[disp_num].flags
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->dither_disp_cfg[mixer_num].flags |=
+			mdss_pp_res->dither_disp_cfg[disp_num].flags |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.gamut_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_GAMUT;
-		if (!(mdss_pp_res->gamut_disp_cfg[mixer_num].flags
+		if (!(mdss_pp_res->gamut_disp_cfg[disp_num].flags
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->gamut_disp_cfg[mixer_num].flags |=
+			mdss_pp_res->gamut_disp_cfg[disp_num].flags |=
 				MDP_PP_OPS_WRITE;
 	}
 	if (pp_sts.pgc_sts & PP_STS_ENABLE) {
 		flags |= PP_FLAGS_DIRTY_PGC;
-		if (!(mdss_pp_res->pgc_disp_cfg[mixer_num].flags
+		if (!(mdss_pp_res->pgc_disp_cfg[disp_num].flags
 					& MDP_PP_OPS_DISABLE))
-			mdss_pp_res->pgc_disp_cfg[mixer_num].flags |=
+			mdss_pp_res->pgc_disp_cfg[disp_num].flags |=
 				MDP_PP_OPS_WRITE;
 	}
 
-	mdss_pp_res->pp_disp_flags[mixer_num] = flags;
+	mdss_pp_res->pp_disp_flags[disp_num] |= flags;
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 60f05ca..d1f0c8d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -520,6 +520,11 @@
 		}
 	}
 
+	if (!*start) {
+		pr_err("start address is zero!\n");
+		return -ENOMEM;
+	}
+
 	if (!ret && (img->offset < data->len)) {
 		data->addr += img->offset;
 		data->len -= img->offset;
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index a3a1a4e..3c11317 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -190,7 +190,7 @@
 
 static irqreturn_t mhl_tx_isr(int irq, void *dev_id);
 static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl,
-			enum mhl_st_type to_mode);
+			enum mhl_st_type to_mode, bool hpd_off);
 static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl,
 				  bool mhl_disc_en);
 
@@ -703,9 +703,18 @@
 }
 
 
-static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl, enum mhl_st_type to_mode)
+static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl, enum mhl_st_type to_mode,
+			bool hpd_off)
 {
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	unsigned long flags;
+	int rc;
+	struct msm_hdmi_mhl_ops *hdmi_mhl_ops = mhl_ctrl->hdmi_mhl_ops;
+
+	pr_debug("%s: tx pwr on\n", __func__);
+	spin_lock_irqsave(&mhl_ctrl->lock, flags);
+	mhl_ctrl->tx_powered_off = false;
+	spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
 
 	switch (to_mode) {
 	case POWER_STATE_D0_NO_MHL:
@@ -722,8 +731,11 @@
 		mhl_ctrl->cur_state = to_mode;
 		break;
 	case POWER_STATE_D3:
-		if (mhl_ctrl->cur_state == POWER_STATE_D3)
+		if (mhl_ctrl->cur_state == POWER_STATE_D3) {
+			pr_debug("%s: mhl tx already in low power mode\n",
+				__func__);
 			break;
+		}
 
 		/* Force HPD to 0 when not in MHL mode.  */
 		mhl_drive_hpd(mhl_ctrl, HPD_DOWN);
@@ -736,7 +748,12 @@
 		msleep(50);
 		if (!mhl_ctrl->disc_enabled)
 			MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00);
-		MHL_SII_PAGE3_MOD(0x003D, BIT0, 0x00);
+		if (hdmi_mhl_ops && hpd_off) {
+			rc = hdmi_mhl_ops->set_upstream_hpd(
+				mhl_ctrl->pdata->hdmi_pdev, 0);
+			pr_debug("%s: hdmi unset hpd %s\n", __func__,
+				 rc ? "failed" : "passed");
+		}
 		mhl_ctrl->cur_state = POWER_STATE_D3;
 		break;
 	default:
@@ -744,6 +761,22 @@
 	}
 }
 
+static bool is_mhl_powered(void *mhl_ctx)
+{
+	struct mhl_tx_ctrl *mhl_ctrl = (struct mhl_tx_ctrl *)mhl_ctx;
+	unsigned long flags;
+	bool r = false;
+
+	spin_lock_irqsave(&mhl_ctrl->lock, flags);
+	if (mhl_ctrl->tx_powered_off)
+		r = false;
+	else
+		r = true;
+	spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+
+	pr_debug("%s: ret pwr state as %x\n", __func__, r);
+	return r;
+}
 
 void mhl_tmds_ctrl(struct mhl_tx_ctrl *mhl_ctrl, uint8_t on)
 {
@@ -759,6 +792,7 @@
 void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state)
 {
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	unsigned long flags;
 
 	pr_debug("%s: To state=[0x%x]\n", __func__, to_state);
 	if (to_state == HPD_UP) {
@@ -769,10 +803,13 @@
 		 * propogate to src let HPD float by clearing
 		 * HPD OUT OVRRD EN
 		 */
-		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, 0x00);
+		spin_lock_irqsave(&mhl_ctrl->lock, flags);
+		mhl_ctrl->tx_powered_off = false;
+		spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, 0);
 	} else {
 		/* Drive HPD to DOWN state */
-		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, BIT4);
+		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, (BIT4 | BIT5), BIT4);
 	}
 }
 
@@ -789,9 +826,7 @@
 		pr_err("%s: cur st not D0\n", __func__);
 		return;
 	}
-	/* spin_lock_irqsave(&mhl_state_lock, flags); */
-	switch_mode(mhl_ctrl, POWER_STATE_D0_MHL);
-	/* spin_unlock_irqrestore(&mhl_state_lock, flags); */
+	switch_mode(mhl_ctrl, POWER_STATE_D0_MHL, true);
 
 	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0x10);
 	MHL_SII_CBUS_WR(0x07, 0xF2);
@@ -823,19 +858,29 @@
 static void mhl_msm_disconnection(struct mhl_tx_ctrl *mhl_ctrl)
 {
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
-	/*
-	 * MHL TX CTL1
-	 * Disabling Tx termination
-	 */
-	MHL_SII_PAGE3_WR(0x30, 0xD0);
+	unsigned long flags;
 
-	switch_mode(mhl_ctrl, POWER_STATE_D3);
+	spin_lock_irqsave(&mhl_ctrl->lock, flags);
+	mhl_ctrl->dwnstream_hpd &= ~BIT6;
+	spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+
+	/* disabling Tx termination */
+	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0);
+	switch_mode(mhl_ctrl, POWER_STATE_D3, true);
 }
 
 static int  mhl_msm_read_rgnd_int(struct mhl_tx_ctrl *mhl_ctrl)
 {
 	uint8_t rgnd_imp;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	struct msm_hdmi_mhl_ops *hdmi_mhl_ops = mhl_ctrl->hdmi_mhl_ops;
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&mhl_ctrl->lock, flags);
+	mhl_ctrl->tx_powered_off = false;
+	spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+
 	/* DISC STATUS REG 2 */
 	rgnd_imp = (mhl_i2c_reg_read(client, TX_PAGE_3, 0x001C) &
 		    (BIT1 | BIT0));
@@ -843,6 +888,12 @@
 
 	if (0x02 == rgnd_imp) {
 		pr_debug("%s: mhl sink\n", __func__);
+		if (hdmi_mhl_ops) {
+			rc = hdmi_mhl_ops->set_upstream_hpd(
+				mhl_ctrl->pdata->hdmi_pdev, 1);
+			pr_debug("%s: hdmi set hpd %s\n", __func__,
+				 rc ? "failed" : "passed");
+		}
 		mhl_ctrl->mhl_mode = 1;
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
@@ -850,7 +901,7 @@
 	} else {
 		pr_debug("%s: non-mhl sink\n", __func__);
 		mhl_ctrl->mhl_mode = 0;
-		switch_mode(mhl_ctrl, POWER_STATE_D3);
+		switch_mode(mhl_ctrl, POWER_STATE_D3, true);
 	}
 	complete(&mhl_ctrl->rgnd_done);
 	return mhl_ctrl->mhl_mode ?
@@ -904,9 +955,9 @@
 }
 
 
-static void dev_detect_isr(struct mhl_tx_ctrl *mhl_ctrl)
+static int dev_detect_isr(struct mhl_tx_ctrl *mhl_ctrl)
 {
-	uint8_t status, reg ;
+	uint8_t status, reg;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 
 	/* INTR_STATUS4 */
@@ -916,13 +967,13 @@
 	if ((0x00 == status) &&\
 	    (mhl_ctrl->cur_state == POWER_STATE_D3)) {
 		pr_err("%s: invalid intr\n", __func__);
-		return;
+		return 0;
 	}
 
 	if (0xFF == status) {
 		pr_debug("%s: invalid intr 0xff\n", __func__);
 		MHL_SII_REG_NAME_WR(REG_INTR4, status);
-		return;
+		return 0;
 	}
 
 	if ((status & BIT0) && (mhl_ctrl->chip_rev_id < 1)) {
@@ -940,31 +991,35 @@
 		mhl_msm_connection(mhl_ctrl);
 	} else if (status & BIT3) {
 		pr_debug("%s: uUSB-a type dev detct\n", __func__);
+
 		/* Short RGND */
 		MHL_SII_REG_NAME_MOD(REG_DISC_STAT2, BIT0 | BIT1, 0x00);
 		mhl_msm_disconnection(mhl_ctrl);
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
 			mhl_ctrl->notify_usb_online(0);
+		return -EACCES;
 	}
 
 	if (status & BIT5) {
 		/* clr intr - reg int4 */
 		pr_debug("%s: mhl discon: int4 st=%02X\n", __func__,
 			 (int)status);
+
 		reg = MHL_SII_REG_NAME_RD(REG_INTR4);
 		MHL_SII_REG_NAME_WR(REG_INTR4, reg);
 		mhl_msm_disconnection(mhl_ctrl);
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
 			mhl_ctrl->notify_usb_online(0);
+		return -EACCES;
 	}
 
 	if ((mhl_ctrl->cur_state != POWER_STATE_D0_NO_MHL) &&\
 	    (status & BIT6)) {
 		/* rgnd rdy Intr */
 		pr_debug("%s: rgnd ready intr\n", __func__);
-		switch_mode(mhl_ctrl, POWER_STATE_D0_NO_MHL);
+		switch_mode(mhl_ctrl, POWER_STATE_D0_NO_MHL, true);
 		mhl_msm_read_rgnd_int(mhl_ctrl);
 	}
 
@@ -981,6 +1036,7 @@
 		release_usb_switch_open(mhl_ctrl);
 	}
 	MHL_SII_REG_NAME_WR(REG_INTR4, status);
+	return 0;
 }
 
 static void mhl_misc_isr(struct mhl_tx_ctrl *mhl_ctrl)
@@ -1000,10 +1056,13 @@
 
 static void mhl_hpd_stat_isr(struct mhl_tx_ctrl *mhl_ctrl)
 {
-	uint8_t intr_1_stat;
-	uint8_t cbus_stat;
+	uint8_t intr_1_stat, cbus_stat, t;
+	unsigned long flags;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 
+	if (!is_mhl_powered(mhl_ctrl))
+		return;
+
 	/* INTR STATUS 1 */
 	intr_1_stat = MHL_SII_PAGE0_RD(0x0071);
 
@@ -1012,6 +1071,7 @@
 
 	/* Clear interrupts */
 	MHL_SII_PAGE0_WR(0x0071, intr_1_stat);
+
 	if (BIT6 & intr_1_stat) {
 		/*
 		 * HPD status change event is pending
@@ -1019,11 +1079,26 @@
 		 * MSC REQ ABRT REASON
 		 */
 		cbus_stat = MHL_SII_CBUS_RD(0x0D);
-		if (BIT6 & cbus_stat)
-			mhl_drive_hpd(mhl_ctrl, HPD_UP);
-		else
-			mhl_drive_hpd(mhl_ctrl, HPD_DOWN);
+		pr_debug("%s: cbus_stat=[0x%02x] cur_pwr=[%u]\n",
+			 __func__, cbus_stat, mhl_ctrl->cur_state);
 
+		spin_lock_irqsave(&mhl_ctrl->lock, flags);
+		t = mhl_ctrl->dwnstream_hpd;
+		spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+
+		if (BIT6 & (cbus_stat ^ t)) {
+			u8 status = cbus_stat & BIT6;
+			mhl_drive_hpd(mhl_ctrl, status ? HPD_UP : HPD_DOWN);
+			if (!status) {
+				MHL_SII_PAGE1_MOD(0x003D, BIT0, 0x00);
+				spin_lock_irqsave(&mhl_ctrl->lock, flags);
+				mhl_ctrl->tx_powered_off = true;
+				spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+			}
+			spin_lock_irqsave(&mhl_ctrl->lock, flags);
+			mhl_ctrl->dwnstream_hpd = cbus_stat;
+			spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
+		}
 	}
 }
 
@@ -1257,122 +1332,9 @@
 
 }
 
-static void clear_all_intrs(struct i2c_client *client)
-{
-	uint8_t regval = 0x00;
-
-	pr_debug_intr("********* exiting isr mask check ?? *************\n");
-	pr_debug_intr("int1 mask = %02X\n",
-		(int) MHL_SII_REG_NAME_RD(REG_INTR1));
-	pr_debug_intr("int3 mask = %02X\n",
-		(int) MHL_SII_PAGE0_RD(0x0077));
-	pr_debug_intr("int4 mask = %02X\n",
-		(int) MHL_SII_REG_NAME_RD(REG_INTR4));
-	pr_debug_intr("int5 mask = %02X\n",
-		(int) MHL_SII_REG_NAME_RD(REG_INTR5));
-	pr_debug_intr("cbus1 mask = %02X\n",
-		(int) MHL_SII_CBUS_RD(0x0009));
-	pr_debug_intr("cbus2 mask = %02X\n",
-		(int) MHL_SII_CBUS_RD(0x001F));
-	pr_debug_intr("********* end of isr mask check *************\n");
-
-	regval = MHL_SII_REG_NAME_RD(REG_INTR1);
-	pr_debug_intr("int1 st = %02X\n", (int)regval);
-	MHL_SII_REG_NAME_WR(REG_INTR1, regval);
-
-	regval =  MHL_SII_REG_NAME_RD(REG_INTR2);
-	pr_debug_intr("int2 st = %02X\n", (int)regval);
-	MHL_SII_REG_NAME_WR(REG_INTR2, regval);
-
-	regval =  MHL_SII_PAGE0_RD(0x0073);
-	pr_debug_intr("int3 st = %02X\n", (int)regval);
-	MHL_SII_PAGE0_WR(0x0073, regval);
-
-	regval =  MHL_SII_REG_NAME_RD(REG_INTR4);
-	pr_debug_intr("int4 st = %02X\n", (int)regval);
-	MHL_SII_REG_NAME_WR(REG_INTR4, regval);
-
-	regval =  MHL_SII_REG_NAME_RD(REG_INTR5);
-	pr_debug_intr("int5 st = %02X\n", (int)regval);
-	MHL_SII_REG_NAME_WR(REG_INTR5, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x0008);
-	pr_debug_intr("cbusInt st = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x0008, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x001E);
-	pr_debug_intr("CBUS intR_2: %d\n", (int)regval);
-	MHL_SII_CBUS_WR(0x001E, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00A0);
-	pr_debug_intr("A0 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00A0, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00A1);
-	pr_debug_intr("A1 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00A1, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00A2);
-	pr_debug_intr("A2 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00A2, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00A3);
-	pr_debug_intr("A3 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00A3, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00B0);
-	pr_debug_intr("B0 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00B0, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00B1);
-	pr_debug_intr("B1 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00B1, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00B2);
-	pr_debug_intr("B2 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00B2, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00B3);
-	pr_debug_intr("B3 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00B3, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00E0);
-	pr_debug_intr("E0 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00E0, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00E1);
-	pr_debug_intr("E1 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00E1, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00E2);
-	pr_debug_intr("E2 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00E2, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00E3);
-	pr_debug_intr("E3 st set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00E3, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00F0);
-	pr_debug_intr("F0 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00F0, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00F1);
-	pr_debug_intr("F1 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00F1, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00F2);
-	pr_debug_intr("F2 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00F2, regval);
-
-	regval =  MHL_SII_CBUS_RD(0x00F3);
-	pr_debug_intr("F3 int set = %02X\n", (int)regval);
-	MHL_SII_CBUS_WR(0x00F3, regval);
-	pr_debug_intr("********* end of exiting in isr *************\n");
-}
-
-
 static irqreturn_t mhl_tx_isr(int irq, void *data)
 {
+	int rc;
 	struct mhl_tx_ctrl *mhl_ctrl = (struct mhl_tx_ctrl *)data;
 	pr_debug("%s: Getting Interrupts\n", __func__);
 
@@ -1380,28 +1342,27 @@
 	 * Check RGND, MHL_EST, CBUS_LOCKOUT, SCDT
 	 * interrupts. In D3, we get only RGND
 	 */
-	dev_detect_isr(mhl_ctrl);
+	rc = dev_detect_isr(mhl_ctrl);
+	if (rc)
+		pr_debug("%s: dev_detect_isr rc=[%d]\n", __func__, rc);
 
 	pr_debug("%s: cur pwr state is [0x%x]\n",
 		 __func__, mhl_ctrl->cur_state);
-	if (mhl_ctrl->cur_state == POWER_STATE_D0_MHL) {
-		/*
-		 * If dev_detect_isr() didn't move the tx to D3
-		 * on disconnect, continue to check other
-		 * interrupt sources.
-		 */
-		mhl_misc_isr(mhl_ctrl);
 
-		/*
-		 * Check for any peer messages for DCAP_CHG, MSC etc
-		 * Dispatch to have the CBUS module working only
-		 * once connected.
-		 */
-		mhl_cbus_isr(mhl_ctrl);
-		mhl_hpd_stat_isr(mhl_ctrl);
-	}
+	/*
+	 * If dev_detect_isr() didn't move the tx to D3
+	 * on disconnect, continue to check other
+	 * interrupt sources.
+	 */
+	mhl_misc_isr(mhl_ctrl);
 
-	clear_all_intrs(mhl_ctrl->i2c_handle);
+	/*
+	 * Check for any peer messages for DCAP_CHG, MSC etc
+	 * Dispatch to have the CBUS module working only
+	 * once connected.
+	 */
+	mhl_cbus_isr(mhl_ctrl);
+	mhl_hpd_stat_isr(mhl_ctrl);
 
 	return IRQ_HANDLED;
 }
@@ -1410,6 +1371,13 @@
 {
 	uint8_t chip_rev_id = 0x00;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	unsigned long flags;
+
+
+	spin_lock_irqsave(&mhl_ctrl->lock, flags);
+	mhl_ctrl->dwnstream_hpd = 0;
+	mhl_ctrl->tx_powered_off = false;
+	spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
 
 	/* Reset the TX chip */
 	mhl_sii_reset_pin(mhl_ctrl, 0);
@@ -1428,7 +1396,7 @@
 	 * MHL-USB handshake is implemented
 	 */
 	mhl_init_reg_settings(mhl_ctrl, true);
-	switch_mode(mhl_ctrl, POWER_STATE_D3);
+	switch_mode(mhl_ctrl, POWER_STATE_D3, true);
 	return 0;
 }
 
@@ -1710,6 +1678,7 @@
 	mhl_ctrl->cur_state = POWER_STATE_D0_MHL;
 	INIT_LIST_HEAD(&mhl_ctrl->list_cmd);
 	init_completion(&mhl_ctrl->msc_cmd_done);
+	spin_lock_init(&mhl_ctrl->lock);
 	mhl_ctrl->msc_send_workqueue = create_singlethread_workqueue
 		("mhl_msc_cmd_queue");
 
@@ -1813,7 +1782,7 @@
 	pr_debug("%s: i2c client addr is [%x]\n", __func__, client->addr);
 	if (mhl_ctrl->pdata->hdmi_pdev) {
 		rc = msm_hdmi_register_mhl(mhl_ctrl->pdata->hdmi_pdev,
-					   hdmi_mhl_ops);
+					   hdmi_mhl_ops, mhl_ctrl);
 		if (rc) {
 			pr_err("%s: register with hdmi failed\n", __func__);
 			rc = -EPROBE_DEFER;
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index d8eb494..a66a411 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -158,6 +158,9 @@
 	int scrpd_busy;
 	int wr_burst_pending;
 	struct completion req_write_done;
+	spinlock_t lock;
+	bool tx_powered_off;
+	uint8_t dwnstream_hpd;
 };
 
 int mhl_i2c_reg_read(struct i2c_client *client,
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 74b09cb..4bce95c 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -700,6 +700,7 @@
 #define V4L2_QCOM_BUF_FLAG_CODECCONFIG  0x4000
 #define V4L2_QCOM_BUF_FLAG_EOSEQ  0x8000
 #define V4L2_QCOM_BUF_TIMESTAMP_INVALID 0x10000
+#define V4L2_QCOM_BUF_FLAG_DECODEONLY 0x40000
 
 /*
  *	O V E R L A Y   P R E V I E W
diff --git a/include/media/radio-iris-commands.h b/include/media/radio-iris-commands.h
index d41baa9..0b3331a 100644
--- a/include/media/radio-iris-commands.h
+++ b/include/media/radio-iris-commands.h
@@ -71,6 +71,7 @@
 	V4L2_CID_PRIVATE_CF0TH12,
 	V4L2_CID_PRIVATE_SINRFIRSTSTAGE,
 	V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE,
+	V4L2_CID_PRIVATE_RXREPEATCOUNT,
 
 	/*using private CIDs under userclass*/
 	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 53602c5..d6151c0 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -73,6 +73,9 @@
 #define CF0TH12_BYTE4_OFFSET   11
 #define MAX_SINR_FIRSTSTAGE	127
 #define MAX_RMSSI_FIRSTSTAGE	127
+#define RDS_PS0_XFR_MODE 0x01
+#define RDS_PS0_LEN 6
+#define RX_REPEATE_BYTE_OFFSET 5
 
 /* HCI timeouts */
 #define RADIO_HCI_TIMEOUT	(10000)	/* 10 seconds */
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index f064837..01e30d0 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6928,4 +6928,10 @@
 	struct afe_port_param_data_v2 pdata;
 	struct afe_param_id_clip_bank_sel bank_sel;
 } __packed;
+
+/* Ultrasound supported formats */
+#define US_POINT_EPOS_FORMAT 0x00012310
+#define US_RAW_FORMAT        0x0001127C
+#define US_PROX_FORMAT       0x0001272B
+
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 81636a3..a7933a4 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1262,7 +1262,7 @@
 #define MPEG4_MULTI_AAC 0x00010D86
 #define US_POINT_EPOS_FORMAT 0x00012310
 #define US_RAW_FORMAT        0x0001127C
-#define US_PROX_FORMAT       0x00012721
+#define US_PROX_FORMAT       0x0001272B
 #define MULTI_CHANNEL_PCM    0x00010C66
 
 #define ASM_ENCDEC_SBCRATE         0x00010C13
diff --git a/kernel/timer.c b/kernel/timer.c
index 24c5d20..cf7217a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1679,12 +1679,12 @@
 			boot_done = 1;
 			base = &boot_tvec_bases;
 		}
+		spin_lock_init(&base->lock);
 		tvec_base_done[cpu] = 1;
 	} else {
 		base = per_cpu(tvec_bases, cpu);
 	}
 
-	spin_lock_init(&base->lock);
 
 	for (j = 0; j < TVN_SIZE; j++) {
 		INIT_LIST_HEAD(base->tv5.vec + j);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index daba6d5..a37b4eb 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -2786,6 +2786,7 @@
 	wcd9xxx_turn_onoff_rel_detection(codec, true);
 
 	pr_debug("%s: leave\n", __func__);
+	return;
 
 gen_err:
 	pr_err("%s: Error returned, ret: %d\n", __func__, ret);
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index 1f7712f..4db3ea5 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -759,45 +759,6 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
-	/* Incall Record Uplink BACK END DAI Link */
-	{
-		.name = LPASS_BE_INCALL_RECORD_TX,
-		.stream_name = "Voice Uplink Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.32772",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Incall Record Downlink BACK END DAI Link */
-	{
-		.name = LPASS_BE_INCALL_RECORD_RX,
-		.stream_name = "Voice Downlink Capture",
-		.cpu_dai_name = "msm-dai-q6-dev.32771",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
-	/* Incall Music BACK END DAI Link */
-	{
-		.name = LPASS_BE_VOICE_PLAYBACK_TX,
-		.stream_name = "Voice Farend Playback",
-		.cpu_dai_name = "msm-dai-q6-dev.32773",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ignore_suspend = 1,
-	},
 };
 
 struct snd_soc_card snd_soc_card_msm8x10 = {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index b5f1b6d..fa476ee 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -1708,6 +1708,24 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new sec_mi2s_rx_voice_mixer_controls[] = {
+	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1889,6 +1907,9 @@
 	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voice", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX_Voice", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
@@ -1958,6 +1979,9 @@
 	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voip", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX_Voip", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
@@ -2693,6 +2717,10 @@
 				SND_SOC_NOPM, 0, 0,
 				sec_i2s_rx_voice_mixer_controls,
 				ARRAY_SIZE(sec_i2s_rx_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_MI2S_RX_Voice Mixer",
+				SND_SOC_NOPM, 0, 0,
+				sec_mi2s_rx_voice_mixer_controls,
+				ARRAY_SIZE(sec_mi2s_rx_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0,
 				slimbus_rx_voice_mixer_controls,
@@ -2945,6 +2973,13 @@
 	{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
 
+	{"SEC_MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SEC_MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
+	{"SEC_MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"SEC_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"SEC_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX_Voice Mixer"},
+
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"SLIM_0_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
@@ -2995,6 +3030,7 @@
 	{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
 
 	{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
+	{"Voice_Tx Mixer", "PRI_MI2S_TX_Voice", "PRI_MI2S_TX"},
 	{"Voice_Tx Mixer", "MI2S_TX_Voice", "MI2S_TX"},
 	{"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
 	{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
@@ -3026,6 +3062,7 @@
 	{"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
 	{"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
 	{"Voip_Tx Mixer", "SEC_AUX_PCM_TX_Voip", "SEC_AUX_PCM_TX"},
+	{"Voip_Tx Mixer", "PRI_MI2S_TX_Voip", "PRI_MI2S_TX"},
 
 	{"VOIP_UL", NULL, "Voip_Tx Mixer"},
 	{"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},