Merge "ASoC: msm8226: Enable Lineout1/2 for speaker on SKUF"
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 514160e..7093fb8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -126,6 +126,11 @@
 - qcom,mdss-has-wfd-blk: Boolean property to indicate the presence of dedicated
 			writeback wfd block in MDSS as opposed to writeback
 			block that is shared between rotator and wfd.
+- qcom,mdss-smp-mb-per-pipe:	Maximum number of shared memory pool blocks
+				restricted for a source surface pipe. If this
+				property is not specified, no such restriction
+				would be applied.
+
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
@@ -161,6 +166,7 @@
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
 		qcom,mdss-smp-data = <22 4096>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-smp-mb-per-pipe = <2>;
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
 		qcom,mdss-has-wfd-blk;
diff --git a/Documentation/devicetree/bindings/input/misc/mpu3050.txt b/Documentation/devicetree/bindings/input/misc/mpu3050.txt
new file mode 100644
index 0000000..edbe147
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mpu3050.txt
@@ -0,0 +1,31 @@
+InvenSense MPU30X0-series gyrometer driver
+
+Required properties:
+
+ - compatible		: Should be "invn,mpu3050".
+ - reg				: i2c slave address of the device.
+ - interrupt-parent	: Parent of interrupt.
+ - interrupts		: Gyrometer sample interrupt to indicate new data ready.
+ - vdd-supply		: Analog power supply needed to power device.
+ - vlogic-supply	: Digital IO power supply needed for IO and I2C.
+ - invn,gpio-int	: GPIO used for interrupt.
+ - invn,gpio-en		: GPIO used for power enabling.
+ - invn,poll-interval	: Initial data polling interval in milliseconds.
+
+Example:
+	i2c@f9925000 {
+		mpu3050@68 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "okay";
+			reg = <0x68>;
+			compatible = "invn,mpu3050";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <84 0x2>;
+			vlogic-supply = <&pm8110_l14>;
+			vdd-supply = <&pm8110_l19>;
+			invn,gpio-int = <&msmgpio 84 0x2>;
+			invn,gpio-en = <&pm8110_gpios 2 0x2>;
+			invn,poll-interval = <200>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
new file mode 100644
index 0000000..2d730e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -0,0 +1,186 @@
+== Introduction ==
+
+Hardware modules that control pin multiplexing or configuration parameters
+such as pull-up/down, tri-state, drive-strength etc are designated as pin
+controllers. Each pin controller must be represented as a node in device tree,
+just like any other hardware module.
+
+Hardware modules whose signals are affected by pin configuration are
+designated client devices. Again, each client device must be represented as a
+node in device tree, just like any other hardware module.
+
+For a client device to operate correctly, certain pin controllers must
+set up certain specific pin configurations. Some client devices need a
+single static pin configuration, e.g. set up during initialization. Others
+need to reconfigure pins at run-time, for example to tri-state pins when the
+device is inactive. Hence, each client device can define a set of named
+states. The number and names of those states is defined by the client device's
+own binding.
+
+The common pinctrl bindings defined in this file provide an infrastructure
+for client device device tree nodes to map those state names to the pin
+configuration used by those states.
+
+Note that pin controllers themselves may also be client devices of themselves.
+For example, a pin controller may set up its own "active" state when the
+driver loads. This would allow representing a board's static pin configuration
+in a single place, rather than splitting it across multiple client device
+nodes. The decision to do this or not somewhat rests with the author of
+individual board device tree files, and any requirements imposed by the
+bindings for the individual client devices in use by that board, i.e. whether
+they require certain specific named states for dynamic pin configuration.
+
+== Pinctrl client devices ==
+
+For each client device individually, every pin state is assigned an integer
+ID. These numbers start at 0, and are contiguous. For each state ID, a unique
+property exists to define the pin configuration. Each state may also be
+assigned a name. When names are used, another property exists to map from
+those names to the integer IDs.
+
+Each client device's own binding determines the set of states the must be
+defined in its device tree node, and whether to define the set of state
+IDs that must be provided, or whether to define the set of state names that
+must be provided.
+
+Required properties:
+pinctrl-0:	List of phandles, each pointing at a pin configuration
+		node. These referenced pin configuration nodes must be child
+		nodes of the pin controller that they configure. Multiple
+		entries may exist in this list so that multiple pin
+		controllers may be configured, or so that a state may be built
+		from multiple nodes for a single pin controller, each
+		contributing part of the overall configuration. See the next
+		section of this document for details of the format of these
+		pin configuration nodes.
+
+		In some cases, it may be useful to define a state, but for it
+		to be empty. This may be required when a common IP block is
+		used in an SoC either without a pin controller, or where the
+		pin controller does not affect the HW module in question. If
+		the binding for that IP block requires certain pin states to
+		exist, they must still be defined, but may be left empty.
+
+Optional properties:
+pinctrl-1:	List of phandles, each pointing at a pin configuration
+		node within a pin controller.
+...
+pinctrl-n:	List of phandles, each pointing at a pin configuration
+		node within a pin controller.
+pinctrl-names:	The list of names to assign states. List entry 0 defines the
+		name for integer state ID 0, list entry 1 for state ID 1, and
+		so on.
+
+For example:
+
+	/* For a client device requiring named states */
+	device {
+		pinctrl-names = "active", "idle";
+		pinctrl-0 = <&state_0_node_a>;
+		pinctrl-1 = <&state_1_node_a &state_1_node_b>;
+	};
+
+	/* For the same device if using state IDs */
+	device {
+		pinctrl-0 = <&state_0_node_a>;
+		pinctrl-1 = <&state_1_node_a &state_1_node_b>;
+	};
+
+	/*
+	 * For an IP block whose binding supports pin configuration,
+	 * but in use on an SoC that doesn't have any pin control hardware
+	 */
+	device {
+		pinctrl-names = "active", "idle";
+		pinctrl-0 = <>;
+		pinctrl-1 = <>;
+	};
+
+== Pin controller devices ==
+
+Pin controller devices should contain the pin configuration nodes that client
+devices reference.
+
+For example:
+
+	pincontroller {
+		... /* Standard DT properties for the device itself elided */
+
+		state_0_node_a {
+			...
+		};
+		state_1_node_a {
+			...
+		};
+		state_1_node_b {
+			...
+		};
+	}
+
+The contents of each of those pin configuration child nodes is defined
+entirely by the binding for the individual pin controller device. There
+exists no common standard for this content.
+
+The pin configuration nodes need not be direct children of the pin controller
+device; they may be grandchildren, for example. Whether this is legal, and
+whether there is any interaction between the child and intermediate parent
+nodes, is again defined entirely by the binding for the individual pin
+controller device.
+
+== Using generic pinconfig options ==
+
+Generic pinconfig parameters can be used by defining a separate node containing
+the applicable parameters (and optional values), like:
+
+pcfg_pull_up: pcfg_pull_up {
+	bias-pull-up;
+	drive-strength = <20>;
+};
+
+This node should then be referenced in the appropriate pinctrl node as a phandle
+and parsed in the driver using the pinconf_generic_parse_dt_config function.
+
+Supported configuration parameters are:
+
+bias-disable		- disable any pin bias
+bias-high-impedance	- high impedance mode ("third-state", "floating")
+bias-bus-hold		- latch weakly
+bias-pull-up		- pull up the pin
+bias-pull-down		- pull down the pin
+bias-pull-pin-default	- use pin-default pull state
+drive-push-pull		- drive actively high and low
+drive-open-drain	- drive with open drain
+drive-open-source	- drive with open source
+drive-strength		- sink or source at most X mA
+input-schmitt-enable	- enable schmitt-trigger mode
+input-schmitt-disable	- disable schmitt-trigger mode
+input-schmitt		- run in schmitt-trigger mode with hysteresis X
+input-debounce		- debounce mode with debound time X
+power-source		- select power source X
+slew-rate		- use slew-rate X
+low-power-enable	- enable low power mode
+low-power-disable	- disable low power mode
+output-low		- set the pin to output mode with low level
+output-high		- set the pin to output mode with high level
+
+Arguments for parameters:
+
+- bias-pull-up, -down and -pin-default take as optional argument 0 to disable
+  the pull, on hardware supporting it the pull strength in Ohm. bias-disable
+  will also disable any active pull.
+
+- drive-strength takes as argument the target strength in mA.
+
+- input-schmitt takes as argument the adjustable hysteresis in a
+  driver-specific format
+
+- input-debounce takes the debounce time as argument or 0 to disable debouncing
+
+- power-source argument is the custom value describing the source to select
+
+- slew-rate takes as argument the target rate in a driver-specific format
+
+All parameters not listed here, do not take an argument.
+
+More in-depth documentation on these parameters can be found in
+<include/linux/pinctrl/pinconfig-generic.h>
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 6e125f2..e3c3555 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -65,10 +65,21 @@
 					detection, "bpd_thm_id" selects both.
 					If the property is not set, the temperatue pin will
 					be used.
+- qcom,btc-disabled:			If flag is set battery hot and cold monitoring is
+					disabled in hardware. This monitoring is turned on
+					by default.
+- qcom,batt-hot-percent:		Specify a supported hot threshold percentage.
+					Supported thresholds: 25% and 35%. If none is specified
+					hardware defaults will be used.
+- qcom,batt-cold-percent:		Specify a supported cold threshold percentage.
+					Supported thresholds: 70% and 80%. If none is specified
+					hardware defaults will be used.
 - otg-parent-supply			Specify a phandle to a parent supply regulator
 					for the OTG regulator.
 - boost-parent-supply			Specify a phandle to a parent supply regulator
 					for the boost regulator.
+- qcom,resume-soc			Capacity in percent at which charging should resume
+					when a fully charged battery drops below this level.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -182,6 +193,9 @@
 		qcom,warm-bat-mv = <4100>;
 		qcom,ibatmax-cool-ma = <350>;
 		qcom,vbatdet-delta-mv = <60>;
+		qcom,batt-hot-percent = <25>;
+		qcom,batt-cold-percent = <85>;
+		qcom,btc-disabled = <0>;
 
 		qcom,chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
index 6b090fa..64f2ddd 100644
--- a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
+++ b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
@@ -44,6 +44,17 @@
  - qcom,rxreg-access: This boolean indicates that slimbus RX should use direct
 		 register access to receive data. This flag is only needed if
 		 BAM pipe is not available to receive data from slimbus
+ - qcom,apps-ch-pipes: This value represents BAM pipe-mask used by application
+		 processor for data channels. If this property is not defined,
+		 default mask of 0x3F000000 is used indicating apps can use 6
+		 pipes from 24-29.
+ - qcom,ea-pc: This value represents product code (PC) field of enumeration
+		 address (EA) for the Qualcomm slimbus controller hardware.
+		 This value is needed if data-channels originating from apps
+		 are to be used, so that application processor can query
+		 logical address of the ported generic device to be used.
+		 Other than PC, fields of EA are same across platforms.
+
 Example:
 	slim@fe12f000 {
 		cell-index = <1>;
@@ -55,4 +66,6 @@
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
 		qcom,min-clk-gear = <10>;
 		qcom,rxreg-access;
+		qcom,apps-ch-pipes = <0x60000000>;
+		qcom,ea-pc = <0x30>;
 	};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index f687e77..ad1b5ad 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -82,6 +82,10 @@
 - qcom,hsusb-l1-supported: If present, the device supports l1 (Link power
 	management).
 - qcom,no-selective-suspend: If present selective suspend is disabled on hub ports.
+- qcom,hsusb-otg-dpsehv-int: If present, indicates mpm interrupt to be configured
+	for detection of dp line transition during VDD minimization.
+- qcom,hsusb-otg-dmsehv-int: If present, indicates mpm interrupt to be configured
+	for detection of dm line transition during VDD minimization.
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
@@ -106,6 +110,8 @@
                 HSUSB_3p3-supply = <&pm8226_l20>;
 		qcom,vdd-voltage-level = <1 5 7>;
 		qcom,dp-manual-pullup;
+		qcom,hsusb-otg-dpsehv-int = <49>;
+		qcom,hsusb-otg-dmsehv-int = <58>;
 		qcom,msm_bus,name = "usb2";
 		qcom,msm_bus,num_cases = <2>;
 		qcom,msm_bus,active_only = <0>;
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0ebbe63..b4bcaf6 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -23,6 +23,7 @@
 ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
 intercontrol	Inter Control Group
+invn	InvenSense Inc.
 linux	Linux-specific binding
 kionix	Kionix Inc.
 marvell	Marvell Technology Group Ltd.
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 311e968..21e92ab 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -14,6 +14,10 @@
 /include/ "msm8974-camera-sensor-dragonboard.dtsi"
 /include/ "msm8974-leds.dtsi"
 
+&vph_pwr_vreg {
+	status = "ok";
+};
+
 &soc {
 	serial@f991e000 {
 		status = "ok";
@@ -62,6 +66,10 @@
 		#size-cells = <1>;
 		ranges;
 		smsc,reset-gpio = <&pm8941_gpios 8 0x00>;
+		/* Dragonboard has an always-on VBUS supply for HSIC hub,
+		 * providing a dummy regulator for the hub driver
+		 */
+		hub_vbus-supply = <&vph_pwr_vreg>;
 
 		hsic_host: hsic@f9a00000 {
 			compatible = "qcom,hsic-host";
@@ -199,6 +207,12 @@
 			"MIC BIAS4 External", "Digital Mic5",
 			"DMIC6", "MIC BIAS4 External",
 			"MIC BIAS4 External", "Digital Mic6";
+
+		qcom,prim-auxpcm-gpio-clk  = <&msmgpio 74 0>;
+		qcom,prim-auxpcm-gpio-sync = <&msmgpio 75 0>;
+		qcom,prim-auxpcm-gpio-din  = <&msmgpio 76 0>;
+		qcom,prim-auxpcm-gpio-dout = <&msmgpio 77 0>;
+		qcom,prim-auxpcm-gpio-set = "prim-gpio-tert";
 	};
 
 	qcom,pronto@fb21b000 {
@@ -525,22 +539,7 @@
 };
 
 &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>;
-	};
+	status = "disabled";
 };
 
 &spmi_bus {
diff --git a/arch/arm/boot/dts/apq8074-v2-cdp.dts b/arch/arm/boot/dts/apq8074-v2-cdp.dts
new file mode 100644
index 0000000..1dc0912
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v2-cdp.dts
@@ -0,0 +1,34 @@
+/* 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/ "msm8974-cdp.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8074v2 CDP";
+	compatible = "qcom,apq8074-cdp", "qcom,apq8074", "qcom,cdp";
+	qcom,msm-id = <184 1 0x20000>;
+};
+
+&usb3 {
+	interrupt-parent = <&usb3>;
+	interrupts = <0 1>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
+
+	qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/apq8084-gpu.dtsi b/arch/arm/boot/dts/apq8084-gpu.dtsi
new file mode 100644
index 0000000..8570b4f
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-gpu.dtsi
@@ -0,0 +1,95 @@
+/* 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.
+ */
+
+&soc {
+	msm_gpu: qcom,kgsl-3d0@fdb00000 {
+		label = "kgsl-3d0";
+		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+		reg = <0xfdb00000 0x10000
+		       0xfdb20000 0x20000>;
+		reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory";
+		interrupts = <0 33 0>;
+		interrupt-names = "kgsl_3d0_irq";
+		qcom,id = <0>;
+
+		qcom,chipid = <0x04020000>;
+
+		qcom,initial-pwrlevel = <2>;
+
+		qcom,idle-timeout = <8>; //<HZ/12>
+		qcom,strtstp-sleepwake;
+		qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE
+
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "grp3d";
+		qcom,msm-bus,num-cases = <5>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+				<26 512 0 0>, <89 604 0 0>,
+				<26 512 0 3144000>, <89 604 0 3200000>,
+				<26 512 0 4800000>, <89 604 0 4800000>,
+				<26 512 0 6400000>, <89 604 0 6400000>,
+				<26 512 0 8528000>, <89 604 0 9600000>;
+
+		/* GDSC oxili regulators */
+		vddcx-supply = <&gdsc_oxili_cx>;
+		vdd-supply = <&gdsc_oxili_gx>;
+
+		/* IOMMU Data */
+		iommu = <&kgsl_iommu>;
+
+		/* Power levels */
+		qcom,gpu-pwrlevels {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			compatible = "qcom,gpu-pwrlevels";
+
+			qcom,gpu-pwrlevel@0 {
+				reg = <0>;
+				qcom,gpu-freq = <600000000>;
+				qcom,bus-freq = <4>;
+				qcom,io-fraction = <33>;
+			};
+
+			qcom,gpu-pwrlevel@1 {
+				reg = <1>;
+				qcom,gpu-freq = <400000000>;
+				qcom,bus-freq = <3>;
+				qcom,io-fraction = <66>;
+			};
+
+			qcom,gpu-pwrlevel@2 {
+				reg = <2>;
+				qcom,gpu-freq = <300000000>;
+				qcom,bus-freq = <2>;
+				qcom,io-fraction = <100>;
+			};
+
+			qcom,gpu-pwrlevel@3 {
+				reg = <3>;
+				qcom,gpu-freq = <200000000>;
+				qcom,bus-freq = <1>;
+				qcom,io-fraction = <100>;
+			};
+
+			qcom,gpu-pwrlevel@4 {
+				reg = <4>;
+				qcom,gpu-freq = <27000000>;
+				qcom,bus-freq = <0>;
+				qcom,io-fraction = <0>;
+			};
+		};
+
+	};
+};
+
diff --git a/arch/arm/boot/dts/apq8084-sim.dts b/arch/arm/boot/dts/apq8084-sim.dts
index e206d4d..dccdbc4 100644
--- a/arch/arm/boot/dts/apq8084-sim.dts
+++ b/arch/arm/boot/dts/apq8084-sim.dts
@@ -171,3 +171,7 @@
 &usb3 {
 	qcom,skip-charger-detection;
 };
+
+&ufs1 {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 39eae2e..7ac286a 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -25,6 +25,7 @@
 /include/ "apq8084-smp2p.dtsi"
 /include/ "apq8084-coresight.dtsi"
 /include/ "apq8084-mdss.dtsi"
+/include/ "apq8084-gpu.dtsi"
 
 &soc {
 	#address-cells = <1>;
@@ -296,6 +297,69 @@
 
 		qcom,firmware-name = "venus";
 	};
+
+	ufs1: ufshc@0xfc598000 {
+		compatible = "jedec,ufs-1.1";
+		reg = <0xfc598000 0x800>;
+		interrupts = <0 28 0>;
+		status = "disabled";
+	};
+};
+
+&gdsc_venus {
+	status = "ok";
+};
+
+&gdsc_venus_core0 {
+	status = "ok";
+};
+
+&gdsc_venus_core1 {
+	status = "ok";
+};
+
+&gdsc_vpu {
+	status = "ok";
+};
+
+&gdsc_mdss {
+	status = "ok";
+};
+
+&gdsc_jpeg {
+	status = "ok";
+};
+
+&gdsc_vfe {
+	status = "ok";
+};
+
+&gdsc_oxili_gx {
+	status = "ok";
+};
+
+&gdsc_oxili_cx {
+	status = "ok";
+};
+
+&gdsc_usb_hsic {
+	status = "ok";
+};
+
+&gdsc_pcie_0{
+	status = "ok";
+};
+
+&gdsc_pcie_1{
+	status = "ok";
+};
+
+&gdsc_usb30{
+	status = "ok";
+};
+
+&gdsc_usb30_sec{
+	status = "ok";
 };
 
 /include/ "msm-pma8084.dtsi"
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 56369dc..4fb2b24 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -14,27 +14,201 @@
 
 &jpeg_iommu {
 	status = "ok";
-	vdd-supply = <&gdsc_jpeg>;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2008
+				0x200c
+				0x2010>;
+
+	qcom,iommu-bfb-data =  <0x3FFF
+				0x4
+				0x4
+				0x0
+				0x0
+				0x10
+				0x50
+				0x0
+				0x2000
+				0x2804
+				0x9614
+				0x0
+				0x0
+				0x0
+				0x0>;
 };
 
 &mdp_iommu {
 	status = "ok";
-	vdd-supply = <&gdsc_mdss>;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018>;
+
+	qcom,iommu-bfb-data =  <0x7FFFFF
+				0x4
+				0x10
+				0x0
+				0x5000
+				0x5a1d
+				0x1822d
+				0x0
+				0x0
+				0x28
+				0x68
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
 };
 
 &venus_iommu {
 	status = "ok";
-	vdd-supply = <&gdsc_venus>;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018
+				0x201c>;
+
+	qcom,iommu-bfb-data =  <0x7FFFFFF
+				0x4
+				0x8
+				0x0
+				0x13607
+				0x4201
+				0x14221
+				0x0
+				0x0
+				0x94
+				0x114
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+
+	venus_ns: qcom,iommu-ctx@fdc8c000 {
+		qcom,iommu-ctx-sids = <0 1 2 3 4 5 7>;
+	};
+
+	venus_sec_bitstream: qcom,iommu-ctx@fdc8d000 {
+		qcom,iommu-ctx-sids = <0x80 0x81 0x82 0x83 0x84>;
+		label = "venus_sec_bitstream";
+	};
+
+	venus_sec_pixel: qcom,iommu-ctx@fdc8f000 {
+		compatible = "qcom,msm-smmu-v1-ctx";
+		reg = <0xfdc8f000 0x1000>;
+		interrupts = <0 42 0>;
+		qcom,iommu-ctx-sids = <0x85>;
+		label = "venus_sec_pixel";
+		qcom,secure-context;
+	};
+
+	venus_sec_non_pixel: qcom,iommu-ctx@fdc90000 {
+		compatible = "qcom,msm-smmu-v1-ctx";
+		reg = <0xfdc90000 0x1000>;
+		interrupts = <0 42 0>;
+		qcom,iommu-ctx-sids = <0x87 0xA0>;
+		label = "venus_sec_non_pixel";
+		qcom,secure-context;
+	};
 };
 
 &kgsl_iommu {
 	status = "ok";
-	qcom,needs-alt-core-clk;
-	vdd-supply = <&gdsc_oxili_cx>;
-	qcom,alt-vdd-supply = <&gdsc_oxili_gx>;
-};
 
-&vfe_iommu {
-	status = "ok";
-	vdd-supply = <&gdsc_vfe>;
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x2008
+				0x2600
+				0x2604
+				0x2608
+				0x260c
+				0x2610
+				0x2614
+				0x2618
+				0x261c
+				0x2620
+				0x2624
+				0x2628
+				0x262c>;
+
+	qcom,iommu-bfb-data =  <0x3
+				0x8
+				0x10
+				0x0
+				0x0
+				0x0
+				0x20
+				0x0
+				0x0
+				0x1
+				0x101
+				0x0
+				0x0
+				0x7
+				0x4
+				0x8
+				0x14
+				0x0
+				0x0
+				0xc
+				0x6c
+				0x0
+				0x8
+				0x10
+				0x0>;
 };
diff --git a/arch/arm/boot/dts/msm-gdsc.dtsi b/arch/arm/boot/dts/msm-gdsc.dtsi
index 78234e8..495f65a 100644
--- a/arch/arm/boot/dts/msm-gdsc.dtsi
+++ b/arch/arm/boot/dts/msm-gdsc.dtsi
@@ -19,6 +19,27 @@
 		status = "disabled";
 	};
 
+	gdsc_venus_core0: qcom,gdsc@fd8c1040 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_venus_core0";
+		reg = <0xfd8c1040 0x4>;
+		status = "disabled";
+	};
+
+	gdsc_venus_core1: qcom,gdsc@fd8c1044 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_venus_core1";
+		reg = <0xfd8c1044 0x4>;
+		status = "disabled";
+	};
+
+	gdsc_vpu: qcom,gdsc@fd8c1404 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_vpu";
+		reg = <0xfd8c1404 0x4>;
+		status = "disabled";
+	};
+
 	gdsc_mdss: qcom,gdsc@fd8c2304 {
 		compatible = "qcom,gdsc";
 		regulator-name = "gdsc_mdss";
@@ -60,4 +81,32 @@
 		reg = <0xfc400404 0x4>;
 		status = "disabled";
 	};
+
+	gdsc_pcie_0: qcom,gdsc@fc401ac4 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_pcie_0";
+		reg = <0xfc401ac4 0x4>;
+		status = "disabled";
+	};
+
+	gdsc_pcie_1: qcom,gdsc@fc401b44 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_pcie_1";
+		reg = <0xfc401b44 0x4>;
+		status = "disabled";
+	};
+
+	gdsc_usb30: qcom,gdsc@fc401e84 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_usb30";
+		reg = <0xfc401e84 0x4>;
+		status = "disabled";
+	};
+
+	gdsc_usb30_sec: qcom,gdsc@fc401ec0 {
+		compatible = "qcom,gdsc";
+		regulator-name = "gdsc_usb30_sec";
+		reg = <0xfc401ec0 0x4>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
index ded9494..1ee7076 100644
--- a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
@@ -427,6 +427,22 @@
 		};
 	};
 
+	rpm-regulator-ldoa25 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <25>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l25 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l25";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
 	rpm-regulator-ldoa26 {
 		compatible = "qcom,rpm-regulator-smd-resource";
 		qcom,resource-name = "ldoa";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b801da8..e72c8cd 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -199,6 +199,7 @@
 			qcom,warm-bat-mv = <4100>;
 			qcom,ibatmax-cool-ma = <350>;
 			qcom,vbatdet-delta-mv = <100>;
+			qcom,resume-soc = <99>;
 			qcom,tchg-mins = <150>;
 
 			qcom,chgr@1000 {
@@ -555,7 +556,7 @@
 			};
 		};
 
-		vadc@3100 {
+		pm8941_vadc: vadc@3100 {
 			compatible = "qcom,qpnp-vadc";
 			reg = <0x3100 0x100>;
 			#address-cells = <1>;
@@ -797,7 +798,7 @@
 			};
 		};
 
-		iadc@3600 {
+		pm8941_iadc: iadc@3600 {
 			compatible = "qcom,qpnp-iadc";
 			reg = <0x3600 0x100>;
 			#address-cells = <1>;
@@ -819,7 +820,7 @@
 			};
 		};
 
-		qcom,vadc@3400 {
+		pm8941_adc_tm: qcom,vadc@3400 {
 			compatible = "qcom,qpnp-adc-tm";
 			reg = <0x3400 0x100>;
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 2be7d1f..11f6369 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -375,4 +375,14 @@
 
 		qcom,hwevent-clks = "core_mmss_clk";
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <30>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index f580897..b895c64 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -36,6 +36,7 @@
 		qcom,mdss-wb-off = <0x00011100 0x00013100>;
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-smp-mb-per-pipe = <2>;
 
 		qcom,vbif-settings = <0x004 0x00000001>,
 				     <0x0D8 0x00000707>,
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 74ecc68..db0620f 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+/include/ "dsi-panel-nt35596-1080p-video.dtsi"
 /include/ "msm8226-camera-sensor-qrd.dtsi"
 
 &soc {
@@ -31,6 +32,33 @@
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
 		};
+		focaltech@38 {
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <17 0x2>;
+			vdd-supply = <&pm8226_l19>;
+			vcc_i2c-supply = <&pm8226_lvs1>;
+			focaltech,family-id = <0x55>;
+			focaltech,reset-gpio = <&msmgpio 16 0x00>;
+			focaltech,irq-gpio = <&msmgpio 17 0x00>;
+			focaltech,display-coords = <0 0 1080 1920>;
+			focaltech,panel-coords = <0 0 1080 2000>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+		};
+	};
+
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "ft5x06_ts";
+		qcom,disp-maxx = <1080>;
+		qcom,disp-maxy = <1920>;
+		qcom,panel-maxx = <1080>;
+		qcom,panel-maxy = <2080>;
+		qcom,key-codes = <139 102 158>;
+		qcom,y-offset = <0>;
 	};
 
 	gpio_keys {
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 8006da2..7f78c84 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -411,6 +411,17 @@
 		};
 	};
 
+	rpm-regulator-ldoa25 {
+		status = "okay";
+		pm8226_l25: regulator-l25 {
+			regulator-name = "8226_l25";
+			regulator-min-microvolt = <1775000>;
+			regulator-max-microvolt = <2125000>;
+			qcom,init-voltage = <1775000>;
+			status = "okay";
+		};
+	};
+
 	rpm-regulator-ldoa26 {
 		status = "okay";
 		pm8226_l26: regulator-l26 {
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index bf94d04..a081308 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -28,5 +28,6 @@
 &soc {
         qcom,mdss_dsi_nt35590_720p_video {
                 status = "ok";
+		qcom,cont-splash-enabled;
         };
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index 3b09d92..a2ad682 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -29,5 +29,6 @@
 &soc {
         qcom,mdss_dsi_nt35590_720p_video {
                 status = "ok";
+		qcom,cont-splash-enabled;
         };
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 527a582..42c1247 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -660,6 +660,21 @@
 		interrupt-names = "core_irq", "bam_irq";
 
 		qcom,bus-width = <8>;
+
+		qcom,msm-bus,name = "sdcc1";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+				<78 512 1600 3200>,    /* 400 KB/s*/
+				<78 512 80000 160000>, /* 20 MB/s */
+				<78 512 100000 200000>, /* 25 MB/s */
+				<78 512 200000 400000>, /* 50 MB/s */
+				<78 512 400000 800000>, /* 100 MB/s */
+				<78 512 400000 800000>, /* 200 MB/s */
+				<78 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
 		status = "disabled";
 	};
 
@@ -672,6 +687,21 @@
 		interrupt-names = "hc_irq", "pwr_irq";
 
 		qcom,bus-width = <8>;
+
+		qcom,msm-bus,name = "sdhc1";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+				<78 512 1600 3200>,    /* 400 KB/s*/
+				<78 512 80000 160000>, /* 20 MB/s */
+				<78 512 100000 200000>, /* 25 MB/s */
+				<78 512 200000 400000>, /* 50 MB/s */
+				<78 512 400000 800000>, /* 100 MB/s */
+				<78 512 400000 800000>, /* 200 MB/s */
+				<78 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
 		status = "disabled";
 	};
 
@@ -687,6 +717,21 @@
 		interrupt-names = "core_irq", "bam_irq";
 
 		qcom,bus-width = <4>;
+
+		qcom,msm-bus,name = "sdcc2";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+				<81 512 1600 3200>,    /* 400 KB/s*/
+				<81 512 80000 160000>, /* 20 MB/s */
+				<81 512 100000 200000>, /* 25 MB/s */
+				<81 512 200000 400000>, /* 50 MB/s */
+				<81 512 400000 800000>, /* 100 MB/s */
+				<81 512 400000 800000>, /* 200 MB/s */
+				<81 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
 		status = "disabled";
 	};
 
@@ -699,6 +744,21 @@
 		interrupt-names = "hc_irq", "pwr_irq";
 
 		qcom,bus-width = <4>;
+
+		qcom,msm-bus,name = "sdhc2";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+				<81 512 1600 3200>,    /* 400 KB/s*/
+				<81 512 80000 160000>, /* 20 MB/s */
+				<81 512 100000 200000>, /* 25 MB/s */
+				<81 512 200000 400000>, /* 50 MB/s */
+				<81 512 400000 800000>, /* 100 MB/s */
+				<81 512 400000 800000>, /* 200 MB/s */
+				<81 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
 		status = "disabled";
 	};
 
@@ -891,6 +951,9 @@
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
 		qcom,freq-control-mask = <0xf>;
+		qcom,core-limit-temp = <80>;
+		qcom,core-temp-hysteresis = <10>;
+		qcom,core-control-mask = <0xe>;
 	};
 
 	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
@@ -945,6 +1008,12 @@
 		reg = <0x0fe805720 0x1000>;
 	};
 
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
+
 	jtag_mm0: jtagmm@fc33c000 {
 		compatible = "qcom,jtag-mm";
 		reg = <0xfc33c000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index d9bb6ab..cef04ef 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -934,9 +934,9 @@
 			qcom,qport = <0>;
 			qcom,ws = <10000>;
 			qcom,mas-hw-id = <0>;
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
-			qcom,prio-lvl = <1>;
+			qcom,prio-rd = <0>;
+			qcom,prio-wr = <0>;
+			qcom,prio-lvl = <0>;
 		};
 
 		mas-mss-proc {
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 7cf6c4f..2041bf6 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -355,4 +355,14 @@
 
 		qcom,hwevent-clks = "core_mmss_clk";
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <28>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 27381e2..352ccf1 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -90,6 +90,23 @@
 		};
 	};
 
+	i2c@f9925000 {
+		mpu3050@68 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "okay";
+			reg = <0x68>;
+			compatible = "invn,mpu3050";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <84 0x2>;
+			vlogic-supply = <&pm8110_l14>;
+			vdd-supply = <&pm8110_l19>;
+			invn,gpio-int = <&msmgpio 84 0x2>;
+			invn,gpio-en = <&pm8110_gpios 2 0x2>;
+			invn,poll-interval = <200>;
+		};
+	};
+
 	gen-vkeys {
 		compatible = "qcom,gen-vkeys";
 		label = "atmel_mxt_ts";
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
new file mode 100644
index 0000000..da02345
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
@@ -0,0 +1,26 @@
+/* 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/ "msm8610-qrd.dtsi"
+/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610 QRD";
+	compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+	qcom,board-id = <11 1>, <11 0>;
+	qcom,msm-id = <147 0>, <165 0>, <161 0>, <162 0>,
+				  <163 0>, <164 0>, <166 0>;
+};
+
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
new file mode 100644
index 0000000..0d79cd5
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -0,0 +1,23 @@
+/* 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/ "msm8610-qrd.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610 QRD";
+	compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+	qcom,board-id = <11 3>;
+	qcom,msm-id = <147 0>, <165 0>, <161 0>, <162 0>,
+				  <163 0>, <164 0>, <166 0>;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dtsi
similarity index 93%
rename from arch/arm/boot/dts/msm8610-qrd.dts
rename to arch/arm/boot/dts/msm8610-qrd.dtsi
index 4a2c57c..7a93c49 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -10,18 +10,23 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
+/* This is a QRD reference design common file. The common device
+ * tree approach would help OEM during development of their extended
+ * device tree. Each new QRD OEM target can select its own include
+ * files and provide board specific overrides in the top level DTS
+ * file.
+ *
+ * For example:
+ * msm8xxx-qrd.dtsi: QRD reference common node
+ * msm8xxx-qrd-skuxx.dts:
+ * /include/ "msm8610-qrd.dtsi"
+ * / {
+ *      List skuxx specific node which is different with QRD
+ *      reference design.
+ * };
+ */
 
 /include/ "msm8610.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
-/include/ "msm8610-qrd-camera-sensor.dtsi"
-
-/ {
-	model = "Qualcomm MSM 8610 QRD";
-	compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
-	qcom,msm-id = <147 11 0>, <165 11 0>, <161 11 0>, <162 11 0>,
-				  <163 11 0>, <164 11 0>, <166 11 0>;
-};
 
 &soc {
 	i2c@f9923000{
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index b99e6f8..15214dd 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -219,6 +219,8 @@
 		HSUSB_1p8-supply = <&pm8110_l10>;
 		HSUSB_3p3-supply = <&pm8110_l20>;
 
+		qcom,hsusb-otg-phy-init-seq =
+			<0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <2>;
@@ -699,6 +701,7 @@
 		gpios = <&msmgpio 23 0>, <&msmgpio 24 0>, <&msmgpio 25 0>, <&msmgpio 26 0>, <&msmgpio 27 0>;
 		qcom,has-pronto-hw;
 		qcom,wlan-rx-buff-count = <256>;
+		qcom,has-autodetect-xo;
 	};
 
 	qcom,mss@fc880000 {
@@ -837,6 +840,12 @@
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
 	};
 
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
+
 	jtag_mm0: jtagmm@fc34c000 {
 		compatible = "qcom,jtag-mm";
 		reg = <0xfc34c000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
index b9f2125..2f8e558 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
@@ -50,12 +50,15 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 90 0>;
+			<&msmgpio 90 0>,
+			<&msmgpio 89 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-req-tbl-num = <0 1>;
-		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
 		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
-					  "CAM_RESET1";
+					  "CAM_RESET1",
+					  "CAM_STANDBY";
 		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
@@ -90,12 +93,15 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 90 0>;
+			<&msmgpio 90 0>,
+			<&msmgpio 89 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-req-tbl-num = <0 1>;
-		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
 		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
-					  "CAM_RESET1";
+					  "CAM_RESET1",
+					  "CAM_STANDBY";
 		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 686cdd8..a162bb7 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -226,6 +226,23 @@
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
+			qcom,mode = "standalone_pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_gdhs";
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <300>;
+			qcom,ss-power = <476>;
+			qcom,energy-overhead = <225300>;
+			qcom,time-overhead = <350>;
+		};
+
+		qcom,lpm-level@4 {
+			reg = <0x4>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_gdhs";
@@ -241,8 +258,8 @@
 			qcom,time-overhead = <5067>;
 		};
 
-		qcom,lpm-level@4 {
-			reg = <0x4>;
+		qcom,lpm-level@5 {
+			reg = <0x5>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_pc";
@@ -258,8 +275,8 @@
 			qcom,time-overhead = <6605>;
 		};
 
-		qcom,lpm-level@5 {
-			reg = <0x5>;
+		qcom,lpm-level@6 {
+			reg = <0x6>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
@@ -273,8 +290,8 @@
 			qcom,time-overhead = <8812>;
 		};
 
-		qcom,lpm-level@6 {
-			reg = <0x6>;
+		qcom,lpm-level@7 {
+			reg = <0x7>;
 			qcom,mode= "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
@@ -288,8 +305,8 @@
 			qcom,time-overhead = <10140>;
 		};
 
-		qcom,lpm-level@7 {
-			reg = <0x7>;
+		qcom,lpm-level@8 {
+			reg = <0x8>;
 			qcom,mode= "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 89cbc4c..181eb9a 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -258,6 +258,8 @@
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-disable-reset;
+		qcom,hsusb-otg-mpm-dpsehv-int = <49>;
+		qcom,hsusb-otg-mpm-dmsehv-int = <58>;
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
@@ -648,6 +650,8 @@
 		reg-names = "slimbus_physical", "slimbus_bam_physical";
 		interrupts = <0 163 0 0 164 0>;
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+		qcom,apps-ch-pipes = <0x60000000>;
+		qcom,ea-pc = <0x30>;
 
 		taiko_codec {
 			compatible = "qcom,taiko-slim-pgd";
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index bde734e..60472c8 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -249,11 +249,22 @@
 	hwevent: hwevent@f9011038 {
 		compatible = "qcom,coresight-hwevent";
 		reg = <0xf9011038 0x8>,
-		      <0xfd4ab160 0x80>;
-		reg-names = "apcs-mux", "ppss-mux";
+		      <0xfd4ab160 0x80>,
+		      <0xfc401600 0x80>;
+		reg-names = "apcs-mux", "ppss-mux", "gcc-mux";
 
 		coresight-id = <20>;
 		coresight-name = "coresight-hwevent";
 		coresight-nr-inports = <0>;
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <21>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 8eb1119..24c6143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -294,4 +294,10 @@
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
+
+	qcom,rpm-rbcpr-stats@fc000000 {
+		compatible = "qcom,rpmrbcpr-stats";
+		reg = <0xfc000000 0x1a0000>;
+		qcom,start-offset = <0x190010>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 638ab6b..f5e930d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -173,7 +173,7 @@
 		qcom,msm-bus,vectors-KBps =
 				<87 512 0 0>,
 				<87 512 40000 640000>;
-		qcom,hsusb-log2-itc = <5>;
+		qcom,hsusb-log2-itc = <4>;
 	};
 
 	hsic_host: hsic@f9a15000 {
@@ -859,6 +859,12 @@
 		qcom,bam-pipe-pair = <2>;
 	};
 
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
+
 	jtag_mm: jtagmm@fc332000 {
 		compatible = "qcom,jtag-mm";
 		reg = <0xfc332000 0x1000>,
diff --git a/arch/arm/boot/dts/msmsamarium-sim.dts b/arch/arm/boot/dts/msmsamarium-sim.dts
index 4acffae..d23bd89 100644
--- a/arch/arm/boot/dts/msmsamarium-sim.dts
+++ b/arch/arm/boot/dts/msmsamarium-sim.dts
@@ -53,3 +53,7 @@
 
 	status = "ok";
 };
+
+&usb_otg {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index e743989..fdf2680 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -177,6 +177,40 @@
 		};
 	};
 
+	android_usb@fe8050c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
+	usb_otg: usb@f9a55000 {
+		compatible = "qcom,hsusb-otg";
+		status = "disabled";
+
+		reg = <0xf9a55000 0x400>;
+		interrupts = <0 134 0>, <0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
+		HSUSB_VDDCX-supply = "";
+		HSUSB_1p8-supply = "";
+		HSUSB_3p3-supply = "";
+		qcom,vdd-voltage-level = <1 5 7>;
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-phy-init-seq =
+			<0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-disable-reset;
+
+		qcom,msm-bus,name = "usb2";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<87 512 0 0>,
+				<87 512 60000 960000>,
+				<87 512 6000  6000>;
+	};
+
 	qcom,bam_dmux@fc834000 {
 		compatible = "qcom,bam_dmux";
 		reg = <0xfc834000 0x7000>;
diff --git a/arch/arm/configs/mpq8092_defconfig b/arch/arm/configs/mpq8092_defconfig
index 5d05596..c870208 100644
--- a/arch/arm/configs/mpq8092_defconfig
+++ b/arch/arm/configs/mpq8092_defconfig
@@ -274,6 +274,7 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
 CONFIG_FB_MSM_MDSS=y
@@ -334,6 +335,7 @@
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU_V1=y
 CONFIG_IOMMU_PGTABLES_L2=y
+CONFIG_IOMMU_NON_SECURE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index f618297..452cd8a 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -27,6 +27,7 @@
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -79,6 +80,7 @@
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_COMPACTION=y
+CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -242,6 +244,8 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index e249d81..fa86cc8 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -27,6 +27,7 @@
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -79,6 +80,7 @@
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_COMPACTION=y
+CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -243,6 +245,8 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
@@ -410,6 +414,7 @@
 CONFIG_QPNP_REVID=y
 CONFIG_MSM_IOMMU_V1=y
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_FUSE=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
 CONFIG_CORESIGHT_FUNNEL=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 010bc10..29ef385 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -385,3 +385,4 @@
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
 CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 7225ec5..1e1b35a 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -376,6 +376,7 @@
 CONFIG_QPNP_REVID=y
 CONFIG_MSM_IOMMU_V0=y
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_FUSE=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
 CONFIG_CORESIGHT_FUNNEL=y
@@ -428,3 +429,4 @@
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
 CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index d02f5da..6471673 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -317,3 +317,4 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 64c8535..863e14f 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -286,6 +286,7 @@
 CONFIG_QPNP_POWER_ON=y
 CONFIG_IPA=y
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_FUSE=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
 CONFIG_CORESIGHT_FUNNEL=y
@@ -327,3 +328,4 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 68e9282..e5a2bb84f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -295,6 +295,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MPQ8092) += gdsc.o
+obj-$(CONFIG_ARCH_APQ8084) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
 obj-$(CONFIG_ARCH_MSMSAMARIUM) += board-samarium.o board-samarium-gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index cdee5b7..8b0acc6 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -57,6 +57,7 @@
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-fluid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-liquid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-mtp.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-liquid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-dragonboard.dtb
 
@@ -119,6 +120,8 @@
    zreladdr-$(CONFIG_ARCH_MSM8610)	:= 0x00008000
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-rumi.dtb
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-sim.dtb
+        dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-qrd-skuaa.dtb
+        dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-qrd-skuab.dtb
 
 # MSMSAMARIUM
    zreladdr-$(CONFIG_ARCH_MSMSAMARIUM)	:= 0x00008000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 98ed2d8..4b6477b 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -899,7 +899,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_v3_pvs0[] __initdata = {
+static struct acpu_level acpu_freq_tbl_pro_pvs0[] __initdata = {
 	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000, 999 },
 	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 999 },
 	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 999 },
@@ -971,17 +971,48 @@
 	[2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
 	[2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
 	[2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+};
 
-	/* 8974v3 Bringup */
-	[3][0] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][1] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][2] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][3] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][4] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][5] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][6] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
-	[3][7] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
+static struct pvs_table pvs_pro[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+	/* Not used by 8974Pro */
+	[0][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[0][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
 
+	/* 8974Pro AB Bringup */
+	[1][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[1][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+
+	/* Not used by 8974Pro */
+	[2][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[2][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+
+	/* 8974Pro Bringup */
+	[3][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+	[3][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
 };
 
 static struct msm_bus_scale_pdata bus_scale_data __initdata = {
@@ -1004,6 +1035,11 @@
 	.stby_khz = 300000,
 };
 
+static void __init apply_pro_bringup_workaround(void)
+{
+	acpuclk_8974_params.pvs_tables = pvs_pro;
+}
+
 static void __init apply_v1_l2_workaround(void)
 {
 	static struct l2_level resticted_l2_tbl[] __initdata = {
@@ -1023,9 +1059,13 @@
 	acpuclk_8974_params.l2_freq_tbl_size = sizeof(resticted_l2_tbl);
 }
 
+#define cpu_is_msm8974pro() (cpu_is_msm8974pro_aa() || cpu_is_msm8974pro_ab() \
+			     || cpu_is_msm8974pro_ac())
+
 static int __init acpuclk_8974_probe(struct platform_device *pdev)
 {
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) {
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1
+	    && cpu_is_msm8974()) {
 		acpuclk_8974_params.pvs_tables = pvs_v1;
 		acpuclk_8974_params.l2_freq_tbl = l2_freq_tbl_v1;
 		bus_scale_data.usecase = bw_level_tbl_v1;
@@ -1043,6 +1083,9 @@
 			apply_v1_l2_workaround();
 	}
 
+	if (cpu_is_msm8974pro())
+		apply_pro_bringup_workaround();
+
 	return acpuclk_krait_init(&pdev->dev, &acpuclk_8974_params);
 }
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f5a9070..362f34d 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -71,7 +71,6 @@
 #include <mach/msm_serial_hs.h>
 #include <sound/cs8427.h>
 #include <media/gpio-ir-recv.h>
-#include <linux/fmem.h>
 #include <mach/msm_pcie.h>
 #include <mach/restart.h>
 #include <mach/msm_iomap.h>
@@ -165,9 +164,6 @@
 };
 #endif
 
-struct fmem_platform_data apq8064_fmem_pdata = {
-};
-
 static struct memtype_reserve apq8064_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
@@ -191,36 +187,28 @@
 	return MEMTYPE_EBI1;
 }
 
-#define FMEM_ENABLED 0
-
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_apq8064_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
-	.reusable = FMEM_ENABLED,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_MIDDLE,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_apq8064_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
-	.reusable = 0,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_HIGH,
 };
 
 static struct ion_co_heap_pdata co_apq8064_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
-	.mem_is_fmem = 0,
 };
 
 static struct ion_co_heap_pdata fw_co_apq8064_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_LOW,
 };
 #endif
@@ -342,12 +330,6 @@
 };
 #endif
 
-static struct platform_device apq8064_fmem_device = {
-	.name = "fmem",
-	.id = 1,
-	.dev = { .platform_data = &apq8064_fmem_pdata },
-};
-
 static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
 				      unsigned long size)
 {
@@ -373,15 +355,10 @@
 }
 
 /**
- * Reserve memory for ION and calculate amount of reusable memory for fmem.
- * We only reserve memory for heaps that are not reusable. However, we only
- * support one reusable heap at the moment so we ignore the reusable flag for
- * other than the first heap with reusable flag set. Also handle special case
+ * Reserve memory for ION. Also handle special case
  * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
  * at a higher address than FW in addition to not more than 256MB away from the
- * base address of the firmware. This means that if MM is reusable the other
- * two heaps must be allocated in the same region as FW. This is handled by the
- * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * base address of the firmware. In addition the MM heap must be
  * adjacent to the FW heap for content protection purposes.
  */
 static void __init reserve_ion_memory(void)
@@ -2502,7 +2479,6 @@
 	&apq8064_device_hsusb_host,
 	&android_usb_device,
 	&msm_device_wcnss_wlan,
-	&apq8064_fmem_device,
 #ifdef CONFIG_ION_MSM
 	&apq8064_ion_dev,
 #endif
@@ -2619,7 +2595,6 @@
 	&android_usb_device,
 	&msm_device_wcnss_wlan,
 	&msm_device_iris_fm,
-	&apq8064_fmem_device,
 #ifdef CONFIG_ION_MSM
 	&apq8064_ion_dev,
 #endif
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index b261ce4..8949609 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -110,6 +110,31 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+/* define gpio used as interrupt input */
+static struct gpiomux_setting gpio_int_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+	.dir = GPIOMUX_IN,
+};
+
+static struct gpiomux_setting gpio_int_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+	.dir = GPIOMUX_IN,
+};
+
+static struct msm_gpiomux_config msm_gpio_int_configs[] __initdata = {
+	{
+		.gpio = 84,
+		.settings = {
+			[GPIOMUX_ACTIVE]	= &gpio_int_act_cfg,
+			[GPIOMUX_SUSPENDED]	= &gpio_int_sus_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
 	{
 		.gpio = 41,
@@ -439,4 +464,6 @@
 				ARRAY_SIZE(msm_keypad_configs));
 	msm_gpiomux_install(sd_card_det, ARRAY_SIZE(sd_card_det));
 	msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+	msm_gpiomux_install(msm_gpio_int_configs,
+			ARRAY_SIZE(msm_gpio_int_configs));
 }
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index e097faf..d79464a 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -79,7 +79,6 @@
 #include <mach/ion.h>
 #include <mach/mdm2.h>
 #include <mach/msm_rtb.h>
-#include <linux/fmem.h>
 #include <mach/msm_cache_dump.h>
 
 #include <mach/kgsl.h>
@@ -183,9 +182,6 @@
 early_param("msm_contig_mem_size", msm_contig_mem_size_setup);
 #endif
 
-struct fmem_platform_data msm8930_fmem_pdata = {
-};
-
 #define DSP_RAM_BASE_8960 0x8da00000
 #define DSP_RAM_SIZE_8960 0x1800000
 static int dspcrashd_pdata_8960 = 0xDEADDEAD;
@@ -230,35 +226,28 @@
 	return MEMTYPE_EBI1;
 }
 
-#define FMEM_ENABLED 0
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_msm8930_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
-	.reusable = FMEM_ENABLED,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_MIDDLE,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_msm8930_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
-	.reusable = 0,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_HIGH,
 };
 
 static struct ion_co_heap_pdata co_msm8930_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
-	.mem_is_fmem = 0,
 };
 
 static struct ion_co_heap_pdata fw_co_msm8930_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_LOW,
 };
 #endif
@@ -382,12 +371,6 @@
 };
 #endif
 
-struct platform_device msm8930_fmem_device = {
-	.name = "fmem",
-	.id = 1,
-	.dev = { .platform_data = &msm8930_fmem_pdata },
-};
-
 static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
 				      unsigned long size)
 {
@@ -413,15 +396,10 @@
 }
 
 /**
- * Reserve memory for ION and calculate amount of reusable memory for fmem.
- * We only reserve memory for heaps that are not reusable. However, we only
- * support one reusable heap at the moment so we ignore the reusable flag for
- * other than the first heap with reusable flag set. Also handle special case
+ * Reserve memory for ION. Also handle special case
  * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
  * at a higher address than FW in addition to not more than 256MB away from the
- * base address of the firmware. This means that if MM is reusable the other
- * two heaps must be allocated in the same region as FW. This is handled by the
- * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * base address of the firmware. In addition the MM heap must be
  * adjacent to the FW heap for content protection purposes.
  */
 static void __init reserve_ion_memory(void)
@@ -2274,7 +2252,6 @@
 #ifdef CONFIG_MSM_FAKE_BATTERY
 	&fish_battery_device,
 #endif
-	&msm8930_fmem_device,
 	&msm_device_bam_dmux,
 	&msm_fm_platform_init,
 
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index b45e690..37567ed 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -86,7 +86,6 @@
 #include <mach/iommu_domains.h>
 
 #include <mach/kgsl.h>
-#include <linux/fmem.h>
 
 #include "timer.h"
 #include "devices.h"
@@ -194,9 +193,6 @@
 early_param("msm_contig_mem_size", msm_contig_mem_size_setup);
 #endif
 
-struct fmem_platform_data msm8960_fmem_pdata = {
-};
-
 #define DSP_RAM_BASE_8960 0x8da00000
 #define DSP_RAM_SIZE_8960 0x1800000
 static int dspcrashd_pdata_8960 = 0xDEADDEAD;
@@ -247,8 +243,6 @@
 static struct ion_cp_heap_pdata cp_mm_msm8960_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = SZ_64K,
-	.reusable = FMEM_ENABLED,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_MIDDLE,
 	.iommu_map_all = 1,
 	.iommu_2x_map_domain = VIDEO_DOMAIN,
@@ -257,21 +251,17 @@
 static struct ion_cp_heap_pdata cp_mfc_msm8960_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
-	.reusable = 0,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_HIGH,
 };
 
 static struct ion_co_heap_pdata co_msm8960_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
-	.mem_is_fmem = 0,
 };
 
 static struct ion_co_heap_pdata fw_co_msm8960_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
-	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_LOW,
 };
 #endif
@@ -394,12 +384,6 @@
 };
 #endif
 
-struct platform_device msm8960_fmem_device = {
-	.name = "fmem",
-	.id = 1,
-	.dev = { .platform_data = &msm8960_fmem_pdata },
-};
-
 static void __init adjust_mem_for_liquid(void)
 {
 	unsigned int i;
@@ -450,15 +434,10 @@
 }
 
 /**
- * Reserve memory for ION and calculate amount of reusable memory for fmem.
- * We only reserve memory for heaps that are not reusable. However, we only
- * support one reusable heap at the moment so we ignore the reusable flag for
- * other than the first heap with reusable flag set. Also handle special case
+ * Reserve memory for ION. Also handle special case
  * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
  * at a higher address than FW in addition to not more than 256MB away from the
- * base address of the firmware. This means that if MM is reusable the other
- * two heaps must be allocated in the same region as FW. This is handled by the
- * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * base address of the firmware. In addition the MM heap must be
  * adjacent to the FW heap for content protection purposes.
  */
 static void __init reserve_ion_memory(void)
@@ -2729,7 +2708,6 @@
 #ifdef CONFIG_BATTERY_BCL
 	&battery_bcl_device,
 #endif
-	&msm8960_fmem_device,
 	&msm_device_bam_dmux,
 	&msm_fm_platform_init,
 #if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE)
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index c8a88d7..6432c93 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -519,6 +519,15 @@
 	},
 };
 
+static struct msm_gpiomux_config msm_epm_configs[] __initdata = {
+	{
+		.gpio      = 81,		/* EPM enable */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_config,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	{
@@ -616,12 +625,6 @@
 			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
-	{
-		.gpio      = 81,		/* EPM enable */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_epm_config,
-		},
-	},
 };
 
 static struct msm_gpiomux_config msm8974_slimbus_config[] __initdata = {
@@ -1233,15 +1236,20 @@
 		msm_gpiomux_install(msm_mhl_configs,
 				    ARRAY_SIZE(msm_mhl_configs));
 
-	if (of_board_is_liquid())
+	if (of_board_is_liquid() ||
+	    (of_board_is_dragonboard() && machine_is_apq8074()))
 		msm_gpiomux_install(msm8974_pri_ter_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_pri_ter_auxpcm_configs));
 	else
 		msm_gpiomux_install(msm8974_pri_pri_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_pri_pri_auxpcm_configs));
 
-	msm_gpiomux_install(msm8974_sec_auxpcm_configs,
+	if (of_board_is_cdp())
+		msm_gpiomux_install(msm8974_sec_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_sec_auxpcm_configs));
+	else
+		msm_gpiomux_install(msm_epm_configs,
+				ARRAY_SIZE(msm_epm_configs));
 
 	msm_gpiomux_install_nowrite(msm_lcd_configs,
 			ARRAY_SIZE(msm_lcd_configs));
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index ef8b5bb..605a7ae 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -307,8 +307,9 @@
 	CLK_DUMMY("",	camss_vfe_vfe1_clk.c,	"", OFF),
 	CLK_DUMMY("",	camss_vfe_vfe_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	camss_vfe_vfe_axi_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_ahb_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_axi_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mdss_byte0_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_byte1_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edpaux_clk.c,	"", OFF),
@@ -319,11 +320,11 @@
 	CLK_DUMMY("",	mdss_extpclk_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_mdp_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_mdp_lut_clk.c,	"", OFF),
+	CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mdss_pclk0_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_pclk1_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_vsync_clk.c,	"", OFF),
+	CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mmss_misc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_axi_clk.c,	"", OFF),
diff --git a/arch/arm/mach-msm/clock-8092.c b/arch/arm/mach-msm/clock-8092.c
index 9de97ea..f8150c4 100644
--- a/arch/arm/mach-msm/clock-8092.c
+++ b/arch/arm/mach-msm/clock-8092.c
@@ -290,6 +290,16 @@
 	CLK_DUMMY("",	vpu_sleep_clk.c,	"", OFF),
 	CLK_DUMMY("",	vpu_vdp_clk.c,	"", OFF),
 	CLK_DUMMY("",	vpu_vdp_xin_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk", NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fd928000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fd928000.qcom,iommu", oFF),
+	CLK_DUMMY("core_clk", NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk", NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", OFF),
 	/* BCSS broadcast */
 	CLK_DUMMY("",	bcc_dem_core_b_clk_src.c,	"", OFF),
 	CLK_DUMMY("",	adc_01_clk_src.c,	"", OFF),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 1e91d5b..1514bba 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -3047,7 +3047,7 @@
 	return branch_reset(&to_pix_rdi_clk(c)->b, action);
 }
 
-static int pix_rdi_clk_list_rate(struct clk *c, unsigned n)
+static long pix_rdi_clk_list_rate(struct clk *c, unsigned n)
 {
 	if (pix_rdi_mux_map[n])
 		return n;
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 4b8fb45..11886a4 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -1401,7 +1401,7 @@
 	F_END
 };
 
-static struct clk_freq_tbl ftbl_gcc_ce1_v3_clk[] = {
+static struct clk_freq_tbl ftbl_gcc_ce1_pro_clk[] = {
 	F( 50000000,  gpll0,  12,   0,   0),
 	F( 75000000,  gpll0,   8,   0,   0),
 	F(100000000,  gpll0,   6,   0,   0),
@@ -1429,7 +1429,7 @@
 	F_END
 };
 
-static struct clk_freq_tbl ftbl_gcc_ce2_v3_clk[] = {
+static struct clk_freq_tbl ftbl_gcc_ce2_pro_clk[] = {
 	F( 50000000,  gpll0,  12,   0,   0),
 	F( 75000000,  gpll0,   8,   0,   0),
 	F(100000000,  gpll0,   6,   0,   0),
@@ -2945,12 +2945,12 @@
 	F_END
 };
 
-static struct clk_freq_tbl ftbl_camss_mclk0_3_v3_clk[] = {
+static struct clk_freq_tbl ftbl_camss_mclk0_3_pro_clk[] = {
 	F_MM( 4800000,    cxo,    4,   0,   0),
 	F_MM( 6000000,  gpll0,   10,   1,  10),
 	F_MM( 8000000,  gpll0,   15,   1,   5),
 	F_MM( 9600000,    cxo,    2,   0,   0),
-	F_MM(16000000,  gpll0,   10,   1,   5),
+	F_MM(16000000,  gpll0, 12.5,   1,   3),
 	F_MM(19200000,    cxo,    1,   0,   0),
 	F_MM(24000000,  gpll0,    5,   1,   5),
 	F_MM(32000000, mmpll0,    5,   1,   5),
@@ -4680,7 +4680,8 @@
 		clk->multiplier = 4;
 		clk_sel = 0x16A;
 
-		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) {
+		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1 &&
+		    cpu_is_msm8974()) {
 			if (measure_mux[i].debug_mux == M_L2)
 				regval = BIT(7)|BIT(0);
 			else
@@ -4871,6 +4872,8 @@
 
 static struct clk_lookup msm_clocks_8974ac_only[] __initdata = {
 	CLK_LOOKUP("gpll4", gpll4_clk_src.c, ""),
+	CLK_LOOKUP("sleep_clk", gcc_sdcc1_cdccal_sleep_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("cal_clk", gcc_sdcc1_cdccal_ff_clk.c, "msm_sdcc.1"),
 };
 
 static struct clk_lookup msm_clocks_8974_common[] __initdata = {
@@ -4982,8 +4985,6 @@
 
 	CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
 	CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
-	CLK_LOOKUP("sleep_clk", gcc_sdcc1_cdccal_sleep_clk.c, "msm_sdcc.1"),
-	CLK_LOOKUP("cal_clk", gcc_sdcc1_cdccal_ff_clk.c, "msm_sdcc.1"),
 	CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
 	CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "msm_sdcc.2"),
 	CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, "msm_sdcc.3"),
@@ -5512,15 +5513,21 @@
 	.mn_ena_mask = BIT(24),
 	.main_output_val = BIT(0),
 	.main_output_mask = BIT(0),
+	.aux_output_val = BIT(1),
+	.aux_output_mask = BIT(1),
 };
 
+#define cpu_is_msm8974pro() (cpu_is_msm8974pro_aa() || cpu_is_msm8974pro_ab() \
+			     || cpu_is_msm8974pro_ac())
+
 static void __init reg_init(void)
 {
 	u32 regval;
 
 	configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
 
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2
+	    || cpu_is_msm8974pro()) {
 		configure_sr_hpm_lp_pll(&mmpll1_v2_config, &mmpll1_regs, 1);
 		configure_sr_hpm_lp_pll(&mmpll3_v2_config, &mmpll3_regs, 0);
 	} else {
@@ -5537,7 +5544,8 @@
 	 * V2 requires additional votes to allow the LPASS and MMSS
 	 * controllers to use GPLL0.
 	 */
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2
+	    || cpu_is_msm8974pro()) {
 		regval = readl_relaxed(
 				GCC_REG_BASE(APCS_CLOCK_BRANCH_ENA_VOTE));
 		writel_relaxed(regval | BIT(26) | BIT(25),
@@ -5547,7 +5555,8 @@
 
 static void __init msm8974_clock_post_init(void)
 {
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2
+	    || cpu_is_msm8974pro()) {
 		clk_set_rate(&axi_clk_src.c, 291750000);
 		clk_set_rate(&ocmemnoc_clk_src.c, 291750000);
 	} else {
@@ -5661,35 +5670,44 @@
 		qup_i2c_clks[i][0]->parent =  qup_i2c_clks[i][1];
 }
 
-/* v2 to v3 clock changes */
-static void __init msm8974_v3_clock_override(void)
+/* v2 to pro clock changes */
+static void __init msm8974_pro_clock_override(void)
 {
 	ce1_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
 	ce1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
-	ce1_clk_src.freq_tbl = ftbl_gcc_ce1_v3_clk;
+	ce1_clk_src.freq_tbl = ftbl_gcc_ce1_pro_clk;
 	ce2_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
 	ce2_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
-	ce2_clk_src.freq_tbl = ftbl_gcc_ce2_v3_clk;
+	ce2_clk_src.freq_tbl = ftbl_gcc_ce2_pro_clk;
 
-	sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
-	sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+	if (cpu_is_msm8974pro_ac()) {
+		sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+		sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+	}
 
 	vfe0_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
 	vfe0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
-	vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
 	vfe1_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
 	vfe1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
-	vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
 	cpp_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
 	cpp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
-	cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+	if (cpu_is_msm8974pro_ab() || cpu_is_msm8974pro_ac()) {
+		vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+		vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+		cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+	} else if (cpu_is_msm8974pro_aa()) {
+		vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 320000000;
+		vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 320000000;
+		cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 320000000;
+	}
 
 	mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 266670000;
 
-	mclk0_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
-	mclk1_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
-	mclk2_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
-	mclk3_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+	mclk0_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
+	mclk1_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
+	mclk2_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
+	mclk3_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
 	mclk0_clk_src.set_rate = set_rate_mnd;
 	mclk1_clk_src.set_rate = set_rate_mnd;
 	mclk2_clk_src.set_rate = set_rate_mnd;
@@ -5733,10 +5751,11 @@
 	msm8974_clock_init_data.size -= ARRAY_SIZE(msm_clocks_8974ac_only);
 
 	/* version specific changes */
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2
+	    || cpu_is_msm8974pro())
 		msm8974_v2_clock_override();
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 3) {
-		msm8974_v3_clock_override();
+	if (cpu_is_msm8974pro()) {
+		msm8974_pro_clock_override();
 		memcpy(msm_clocks_8974 + ARRAY_SIZE(msm_clocks_8974_common),
 		       msm_clocks_8974ac_only, sizeof(msm_clocks_8974ac_only));
 		msm8974_clock_init_data.size +=
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 8ec87d1..c91af54 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -198,11 +198,12 @@
 static int list_rates_show(struct seq_file *m, void *unused)
 {
 	struct clk *clock = m->private;
-	int rate, level, fmax = 0, i = 0;
+	int level, i = 0;
+	unsigned long rate, fmax = 0;
 
 	/* Find max frequency supported within voltage constraints. */
 	if (!clock->vdd_class) {
-		fmax = INT_MAX;
+		fmax = ULONG_MAX;
 	} else {
 		for (level = 0; level < clock->num_fmax; level++)
 			if (clock->fmax[level])
@@ -213,9 +214,9 @@
 	 * List supported frequencies <= fmax. Higher frequencies may appear in
 	 * the frequency table, but are not valid and should not be listed.
 	 */
-	while ((rate = clock->ops->list_rate(clock, i++)) >= 0) {
+	while (!IS_ERR_VALUE(rate = clock->ops->list_rate(clock, i++))) {
 		if (rate <= fmax)
-			seq_printf(m, "%u\n", rate);
+			seq_printf(m, "%lu\n", rate);
 	}
 
 	return 0;
diff --git a/arch/arm/mach-msm/clock-generic.c b/arch/arm/mach-msm/clock-generic.c
index bea82d5..b0d32a0 100644
--- a/arch/arm/mach-msm/clock-generic.c
+++ b/arch/arm/mach-msm/clock-generic.c
@@ -93,6 +93,7 @@
 	struct clk *new_parent = NULL;
 	int rc = 0, i;
 	unsigned long new_par_curr_rate;
+	unsigned long flags;
 
 	for (i = 0; i < mux->num_parents; i++) {
 		if (clk_round_rate(mux->parents[i].src, rate) == rate) {
@@ -108,8 +109,16 @@
 	 * same and the parent might temporarily turn off while switching
 	 * rates.
 	 */
-	if (mux->safe_sel >= 0)
+	if (mux->safe_sel >= 0) {
+		/*
+		 * Some mux implementations might switch to/from a low power
+		 * parent as part of their disable/enable ops. Grab the
+		 * enable lock to avoid racing with these implementations.
+		 */
+		spin_lock_irqsave(&c->lock, flags);
 		rc = mux->ops->set_mux_sel(mux, mux->safe_sel);
+		spin_unlock_irqrestore(&c->lock, flags);
+	}
 	if (rc)
 		return rc;
 
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 0b8240c..18ea514 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -579,7 +579,7 @@
 }
 
 /* Return the nth supported frequency for a given clock. */
-static int rcg_clk_list_rate(struct clk *c, unsigned n)
+static long rcg_clk_list_rate(struct clk *c, unsigned n)
 {
 	struct rcg_clk *rcg = to_rcg_clk(c);
 
@@ -944,7 +944,7 @@
 	return rate > to_cdiv_clk(c)->max_div ? -EPERM : rate;
 }
 
-static int cdiv_clk_list_rate(struct clk *c, unsigned n)
+static long cdiv_clk_list_rate(struct clk *c, unsigned n)
 {
 	return n > to_cdiv_clk(c)->max_div ? -ENXIO : n;
 }
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index fd790e2..b7852fe 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -210,7 +210,7 @@
 }
 
 /* Return the nth supported frequency for a given clock. */
-static int rcg_clk_list_rate(struct clk *c, unsigned n)
+static long rcg_clk_list_rate(struct clk *c, unsigned n)
 {
 	struct rcg_clk *rcg = to_rcg_clk(c);
 
@@ -459,7 +459,7 @@
 	return clk_get_rate(c->parent);
 }
 
-static int branch_clk_list_rate(struct clk *c, unsigned n)
+static long branch_clk_list_rate(struct clk *c, unsigned n)
 {
 	int level, fmax = 0, rate;
 	struct branch_clk *branch = to_branch_clk(c);
@@ -934,7 +934,7 @@
 	return ERR_PTR(-EPERM);
 }
 
-static int cam_mux_clk_list_rate(struct clk *c, unsigned n)
+static long cam_mux_clk_list_rate(struct clk *c, unsigned n)
 {
 	struct cam_mux_clk *mux = to_cam_mux_clk(c);
 	int i;
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 6877b4d9..70b6bea 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -854,11 +854,24 @@
 	return div;
 }
 
+static void dsi_pll_toggle_lock_detect(void)
+{
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x05);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x04);
+	udelay(1);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x05);
+}
+
 static int dsi_pll_lock_status(void)
 {
 	u32 status;
 	int pll_locked = 0;
 
+	dsi_pll_toggle_lock_detect();
+
 	/* poll for PLL ready status */
 	if (readl_poll_timeout_noirq((mdss_dsi_base +
 			DSI_0_PHY_PLL_UNIPHY_PLL_STATUS),
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 69c3751..a251784 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -694,6 +694,12 @@
 		regval |= config->main_output_val;
 	}
 
+	/* Enable the aux output */
+	if (config->aux_output_mask) {
+		regval &= ~config->aux_output_mask;
+		regval |= config->aux_output_val;
+	}
+
 	/* Set pre-divider and post-divider values */
 	regval &= ~config->pre_div_mask;
 	regval |= config->pre_div_val;
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index c4addb2..58c00b9 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -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
@@ -184,6 +184,8 @@
 	u32 mn_ena_mask;
 	u32 main_output_val;
 	u32 main_output_mask;
+	u32 aux_output_val;
+	u32 aux_output_mask;
 };
 
 struct pll_config_regs {
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 1fad7f6..72b5cc1 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -114,7 +114,7 @@
 	int (*set_max_rate)(struct clk *clk, unsigned long rate);
 	int (*set_flags)(struct clk *clk, unsigned flags);
 	unsigned long (*get_rate)(struct clk *clk);
-	int (*list_rate)(struct clk *clk, unsigned n);
+	long (*list_rate)(struct clk *clk, unsigned n);
 	int (*is_enabled)(struct clk *clk);
 	long (*round_rate)(struct clk *clk, unsigned long rate);
 	int (*set_parent)(struct clk *clk, struct clk *parent);
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 5c8f525..95c4fe3 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -79,5 +79,4 @@
 int __init dt_scan_for_memory_hole(unsigned long node, const char *uname,
 					int depth, void *data);
 void adjust_meminfo(unsigned long start, unsigned long size);
-unsigned long __init reserve_memory_for_fmem(unsigned long, unsigned long);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 52102e3..830992c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,6 +32,7 @@
 #define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
 
 #ifdef CONFIG_OF
+#define of_board_is_cdp()	of_machine_is_compatible("qcom,cdp")
 #define of_board_is_sim()	of_machine_is_compatible("qcom,sim")
 #define of_board_is_rumi()	of_machine_is_compatible("qcom,rumi")
 #define of_board_is_fluid()	of_machine_is_compatible("qcom,fluid")
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 7a7fb99..2ce4fa0 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -43,7 +43,6 @@
 /* fixme */
 #include <asm/tlbflush.h>
 #include <../../mm/mm.h>
-#include <linux/fmem.h>
 
 #if defined(CONFIG_ARCH_MSM7X27)
 static void *strongly_ordered_page;
@@ -251,16 +250,6 @@
 		: "=r" (msm_ttbr0));
 }
 
-int request_fmem_c_region(void *unused)
-{
-	return fmem_set_state(FMEM_C_STATE);
-}
-
-int release_fmem_c_region(void *unused)
-{
-	return fmem_set_state(FMEM_T_STATE);
-}
-
 static char * const memtype_names[] = {
 	[MEMTYPE_SMI_KERNEL] = "SMI_KERNEL",
 	[MEMTYPE_SMI]	= "SMI",
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index c572291..ff1fd4f 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -771,7 +771,7 @@
 		ret = request_threaded_irq(desc->proxy_unvote_irq,
 				  NULL,
 				  proxy_unvote_intr_handler,
-				  IRQF_TRIGGER_RISING|IRQF_SHARED,
+				  IRQF_TRIGGER_RISING,
 				  desc->name, desc);
 		if (ret < 0) {
 			dev_err(desc->dev,
diff --git a/arch/arm/mach-msm/pil-msa.c b/arch/arm/mach-msm/pil-msa.c
index a8f5b0e..3a26af9 100644
--- a/arch/arm/mach-msm/pil-msa.c
+++ b/arch/arm/mach-msm/pil-msa.c
@@ -292,25 +292,6 @@
 	.shutdown = pil_msa_pbl_shutdown,
 };
 
-static int pil_msa_mba_make_proxy_votes(struct pil_desc *pil)
-{
-	int ret;
-	struct mba_data *drv = container_of(pil, struct mba_data, desc);
-
-	ret = clk_prepare_enable(drv->xo);
-	if (ret) {
-		dev_err(pil->dev, "Failed to enable XO\n");
-		return ret;
-	}
-	return 0;
-}
-
-static void pil_msa_mba_remove_proxy_votes(struct pil_desc *pil)
-{
-	struct mba_data *drv = container_of(pil, struct mba_data, desc);
-	clk_disable_unprepare(drv->xo);
-}
-
 static int pil_msa_mba_init_image(struct pil_desc *pil,
 				  const u8 *metadata, size_t size)
 {
@@ -400,8 +381,6 @@
 
 struct pil_reset_ops pil_msa_mba_ops = {
 	.init_image = pil_msa_mba_init_image,
-	.proxy_vote = pil_msa_mba_make_proxy_votes,
-	.proxy_unvote = pil_msa_mba_remove_proxy_votes,
 	.verify_blob = pil_msa_mba_verify_blob,
 	.auth_and_reset = pil_msa_mba_auth,
 };
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 4d76c08..1f03fd32 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -429,8 +429,6 @@
 	mba_desc->dev = &pdev->dev;
 	mba_desc->ops = &pil_msa_mba_ops;
 	mba_desc->owner = THIS_MODULE;
-	mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
-	mba_desc->proxy_unvote_irq = clk_ready;
 
 	ret = pil_desc_init(mba_desc);
 	if (ret)
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index 5303009..0c71659 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -48,6 +48,12 @@
 {
 	int rc = 0;
 
+	if ((msm_audio_ion_data.smmu_enabled == true) &&
+	    (msm_audio_ion_data.group == NULL)) {
+		pr_debug("%s:probe is not done, deferred\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
 	*client = msm_audio_ion_client_create(UINT_MAX, name);
 	if (IS_ERR_OR_NULL((void *)(*client))) {
 		pr_err("%s: ION create client for AUDIO failed\n", __func__);
@@ -96,8 +102,10 @@
 
 err_ion_handle:
 	ion_free(*client, *handle);
+	*handle = NULL;
 err_ion_client:
 	msm_audio_ion_client_destroy(*client);
+	*client = NULL;
 err:
 	return -EINVAL;
 }
@@ -143,8 +151,12 @@
 		goto err_ion_handle;
 	}
 
-	if (bufsz != 0)
-		memset((void *)*vaddr, 0, bufsz);
+	*vaddr = ion_map_kernel(*client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto err_ion_handle;
+	}
+	pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz);
 
 	return 0;
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index c97ba68..a6e3497 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3382,8 +3382,9 @@
 	parent_pdev = to_platform_device(pdev->dev.parent);
 
 	key = "irq-reg-base";
-	/* existance check verified in smem driver */
 	r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+	if (!r)
+		goto missing_key;
 	irq_out_size = resource_size(r);
 	irq_out_base = ioremap_nocache(r->start, irq_out_size);
 	if (!irq_out_base) {
@@ -3477,8 +3478,9 @@
 	parent_pdev = to_platform_device(pdev->dev.parent);
 
 	key = "irq-reg-base";
-	/* existance check verified in smem driver */
 	r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+	if (!r)
+		goto missing_key;
 	irq_out_size = resource_size(r);
 	irq_out_base = ioremap_nocache(r->start, irq_out_size);
 	if (!irq_out_base) {
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
index d070e37..b701be8 100644
--- a/arch/arm/mach-msm/test_qmi_client.c
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -61,6 +61,25 @@
 /* Variable to hold the test result */
 static int test_res;
 
+static unsigned int callback_count;
+static void test_async_resp_cb(struct qmi_handle *handle,
+			   unsigned int msg_id, void *msg,
+			   void *resp_cb_data, int stat)
+{
+	callback_count++;
+	if (stat == 0)
+		D("%s invoked %d time(s): [RESP_LEN] = %d, [RESP_VALID] = %d",
+			__func__, callback_count,
+			((struct test_data_resp_msg_v01 *)msg)->data_len,
+			((struct test_data_resp_msg_v01 *)msg)->data_valid);
+	else if (stat < 0)
+		pr_err("%s: Request Failed [MSG_ID]: %d, [ERR_ID]: %d, [Callback_count]: %d",
+			__func__, msg_id, stat,	callback_count);
+
+	kfree(msg);
+	kfree(resp_cb_data);
+}
+
 static int test_qmi_ping_pong_send_sync_msg(void)
 {
 	struct test_ping_req_msg_v01 req;
@@ -138,12 +157,68 @@
 	return rc;
 }
 
+static int test_qmi_data_send_async_msg(unsigned int data_len)
+{
+	struct test_data_req_msg_v01 *req;
+	struct test_data_resp_msg_v01 *resp;
+	struct msg_desc req_desc, *resp_desc;
+	int rc, i;
+
+	req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+	if (!req) {
+		pr_err("%s: Data req msg alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+	if (!resp) {
+		pr_err("%s: Data resp msg alloc failed\n", __func__);
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	resp_desc = kzalloc(sizeof(struct msg_desc), GFP_KERNEL);
+	if (!resp_desc) {
+		pr_err("%s: Resp_desc msg alloc failed\n", __func__);
+		kfree(req);
+		kfree(resp);
+		return -ENOMEM;
+	}
+
+	req->data_len = data_len;
+	for (i = 0; i < data_len; i = i + sizeof(int))
+		memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+	req->client_name_valid = 0;
+
+	req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	req_desc.ei_array = test_data_req_msg_v01_ei;
+
+	resp_desc->max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	resp_desc->msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	resp_desc->ei_array = test_data_resp_msg_v01_ei;
+
+	rc = qmi_send_req_nowait(test_clnt, &req_desc, req, sizeof(*req),
+			       resp_desc, resp, sizeof(*resp),
+			       test_async_resp_cb, (void *)resp_desc);
+	if (rc < 0) {
+		pr_err("%s: send req failed\n", __func__);
+		kfree(resp);
+		kfree(resp_desc);
+	}
+	kfree(req);
+	return rc;
+}
+
 static void test_clnt_recv_msg(struct work_struct *work)
 {
 	int rc;
 
-	rc = qmi_recv_msg(test_clnt);
-	if (rc < 0)
+	do {
+		D("%s: Notified about a Receive Event", __func__);
+	} while ((rc = qmi_recv_msg(test_clnt)) == 0);
+
+	if (rc != -ENOMSG)
 		pr_err("%s: Error receiving message\n", __func__);
 }
 
@@ -280,6 +355,32 @@
 				} while (test_clnt_reset);
 			}
 		}
+	} else if (!strncmp(cmd, "data_async", sizeof(cmd))) {
+		int i;
+		callback_count = 0;
+		for (i = 0; i < test_rep_cnt; i++) {
+			test_res = test_qmi_data_send_async_msg(test_data_sz);
+			if (test_res == -ENETRESET || test_clnt_reset) {
+				--i;
+				do {
+					msleep(50);
+				} while (test_clnt_reset);
+			} else if (test_res < 0) {
+				--i;
+				pr_err("%s: Error sending txn, aborting now",
+					__func__);
+				break;
+			}
+		}
+		while (callback_count < i) {
+			if (test_clnt_reset) {
+				pr_err("%s: Service Exited", __func__);
+				break;
+			}
+			msleep(50);
+		}
+		D("%s complete\n", __func__);
+		callback_count = 0;
 	} else {
 		test_res = -EINVAL;
 	}
diff --git a/block/blk-core.c b/block/blk-core.c
index 8e12c45..40d9b35 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2058,10 +2058,8 @@
 			 * not be passed by new incoming requests
 			 */
 			rq->cmd_flags |= REQ_STARTED;
-			if (rq->cmd_flags & REQ_URGENT) {
-				WARN_ON(q->dispatched_urgent);
+			if (rq->cmd_flags & REQ_URGENT)
 				q->dispatched_urgent = true;
-			}
 			trace_block_rq_issue(q, rq);
 		}
 
@@ -3153,7 +3151,7 @@
 		q->rpm_status = RPM_ACTIVE;
 		__blk_run_queue(q);
 		pm_runtime_mark_last_busy(q->dev);
-		pm_runtime_autosuspend(q->dev);
+		pm_request_autosuspend(q->dev);
 	} else {
 		q->rpm_status = RPM_SUSPENDED;
 	}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 32629e2..b4711cb 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -239,6 +239,9 @@
 	unsigned long workload_expires;
 	struct cfq_group *serving_group;
 
+	unsigned int nr_urgent_pending;
+	unsigned int nr_urgent_in_flight;
+
 	/*
 	 * Each priority tree is sorted by next_request position.  These
 	 * trees are used when determining if two or more queues are
@@ -2091,6 +2094,14 @@
 	(RQ_CFQG(rq))->dispatched++;
 	elv_dispatch_sort(q, rq);
 
+	if (rq->cmd_flags & REQ_URGENT) {
+		if (!cfqd->nr_urgent_pending)
+			WARN_ON(1);
+		else
+			cfqd->nr_urgent_pending--;
+		cfqd->nr_urgent_in_flight++;
+	}
+
 	cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
 	cfqq->nr_sectors += blk_rq_sectors(rq);
 	cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
@@ -3194,6 +3205,69 @@
 	}
 }
 
+/*
+ * Called when a request (rq) is reinserted (to cfqq). Check if there's
+ * something we should do about it
+ */
+static void
+cfq_rq_requeued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+		struct request *rq)
+{
+	struct cfq_io_cq *cic = RQ_CIC(rq);
+
+	cfqd->rq_queued++;
+	if (rq->cmd_flags & REQ_PRIO)
+		cfqq->prio_pending++;
+
+	cfqq->dispatched--;
+	(RQ_CFQG(rq))->dispatched--;
+
+	cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
+
+	cfq_update_io_thinktime(cfqd, cfqq, cic);
+	cfq_update_io_seektime(cfqd, cfqq, rq);
+	cfq_update_idle_window(cfqd, cfqq, cic);
+
+	cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
+
+	if (cfqq == cfqd->active_queue) {
+		if (cfq_cfqq_wait_request(cfqq)) {
+			if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE ||
+			    cfqd->busy_queues > 1) {
+				cfq_del_timer(cfqd, cfqq);
+				cfq_clear_cfqq_wait_request(cfqq);
+			} else {
+				cfq_blkiocg_update_idle_time_stats(
+						&cfqq->cfqg->blkg);
+				cfq_mark_cfqq_must_dispatch(cfqq);
+			}
+		}
+	} else if (cfq_should_preempt(cfqd, cfqq, rq)) {
+		cfq_preempt_queue(cfqd, cfqq);
+	}
+}
+
+static int cfq_reinsert_request(struct request_queue *q, struct request *rq)
+{
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+	struct cfq_queue *cfqq = RQ_CFQQ(rq);
+
+	if (!cfqq || cfqq->cfqd != cfqd)
+		return -EIO;
+
+	cfq_log_cfqq(cfqd, cfqq, "re-insert_request");
+	list_add(&rq->queuelist, &cfqq->fifo);
+	cfq_add_rq_rb(rq);
+
+	cfq_rq_requeued(cfqd, cfqq, rq);
+	if (rq->cmd_flags & REQ_URGENT) {
+			if (cfqd->nr_urgent_in_flight)
+				cfqd->nr_urgent_in_flight--;
+			cfqd->nr_urgent_pending++;
+	}
+	return 0;
+}
+
 static void cfq_insert_request(struct request_queue *q, struct request *rq)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
@@ -3208,7 +3282,45 @@
 	cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
 			&cfqd->serving_group->blkg, rq_data_dir(rq),
 			rq_is_sync(rq));
+
 	cfq_rq_enqueued(cfqd, cfqq, rq);
+
+	if (rq->cmd_flags & REQ_URGENT) {
+		WARN_ON(1);
+		blk_dump_rq_flags(rq, "");
+		rq->cmd_flags &= ~REQ_URGENT;
+	}
+
+	/* Request is considered URGENT if:
+	 * 1. The queue being served is of a lower IO priority then the new
+	 *    request
+	 * OR:
+	 * 2. The workload being performed is ASYNC
+	 * Only READ requests may be considered as URGENT
+	 */
+	if ((cfqd->active_queue &&
+		 cfqq->ioprio_class < cfqd->active_queue->ioprio_class) ||
+		(cfqd->serving_type == ASYNC_WORKLOAD &&
+		 rq_data_dir(rq) == READ)) {
+		rq->cmd_flags |= REQ_URGENT;
+		cfqd->nr_urgent_pending++;
+	}
+}
+
+
+/**
+ * cfq_urgent_pending() - Return TRUE if there is an urgent
+ *			  request on scheduler
+ * @q:	requests queue
+ */
+static bool cfq_urgent_pending(struct request_queue *q)
+{
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+
+	if (cfqd->nr_urgent_pending && !cfqd->nr_urgent_in_flight)
+		return true;
+
+	return false;
 }
 
 /*
@@ -3292,6 +3404,14 @@
 	const int sync = rq_is_sync(rq);
 	unsigned long now;
 
+	if (rq->cmd_flags & REQ_URGENT) {
+		if (!cfqd->nr_urgent_in_flight)
+			WARN_ON(1);
+		else
+			cfqd->nr_urgent_in_flight--;
+		rq->cmd_flags &= ~REQ_URGENT;
+	}
+
 	now = jiffies;
 	cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d",
 		     !!(rq->cmd_flags & REQ_NOIDLE));
@@ -3859,6 +3979,8 @@
 		.elevator_bio_merged_fn =	cfq_bio_merged,
 		.elevator_dispatch_fn =		cfq_dispatch_requests,
 		.elevator_add_req_fn =		cfq_insert_request,
+		.elevator_reinsert_req_fn	= cfq_reinsert_request,
+		.elevator_is_urgent_fn		= cfq_urgent_pending,
 		.elevator_activate_req_fn =	cfq_activate_request,
 		.elevator_deactivate_req_fn =	cfq_deactivate_request,
 		.elevator_completed_req_fn =	cfq_completed_request,
diff --git a/block/elevator.c b/block/elevator.c
index 44193a8..55f1f1e 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -842,7 +842,6 @@
 
 	if (rq->cmd_flags & REQ_URGENT) {
 		q->notified_urgent = false;
-		WARN_ON(!q->dispatched_urgent);
 		q->dispatched_urgent = false;
 	}
 	/*
diff --git a/block/row-iosched.c b/block/row-iosched.c
index 3fa3b1a..8e19c94 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -350,11 +350,14 @@
 	if (row_queues_def[rqueue->prio].idling_enabled) {
 		if (rd->rd_idle_data.idling_queue_idx == rqueue->prio &&
 		    hrtimer_active(&rd->rd_idle_data.hr_timer)) {
-			(void)hrtimer_cancel(&rd->rd_idle_data.hr_timer);
-			row_log_rowq(rd, rqueue->prio,
-				"Canceled delayed work on %d",
-				rd->rd_idle_data.idling_queue_idx);
-			rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
+			if (hrtimer_try_to_cancel(
+				&rd->rd_idle_data.hr_timer) >= 0) {
+				row_log_rowq(rd, rqueue->prio,
+				    "Canceled delayed work on %d",
+				    rd->rd_idle_data.idling_queue_idx);
+				rd->rd_idle_data.idling_queue_idx =
+					ROWQ_MAX_PRIO;
+			}
 		}
 		diff_ms = ktime_to_ms(ktime_sub(ktime_get(),
 				rqueue->idle_data.last_insert_time));
@@ -583,14 +586,14 @@
 	for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) {
 		if (!list_empty(&rd->row_queues[i].fifo)) {
 			if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
-				(void)hrtimer_cancel(
-					&rd->rd_idle_data.hr_timer);
-				row_log_rowq(rd,
-					rd->rd_idle_data.idling_queue_idx,
+				if (hrtimer_try_to_cancel(
+					&rd->rd_idle_data.hr_timer) >= 0) {
+					row_log(rd->dispatch_queue,
 					"Canceling delayed work on %d. RT pending",
-					rd->rd_idle_data.idling_queue_idx);
-				rd->rd_idle_data.idling_queue_idx =
-					ROWQ_MAX_PRIO;
+					     rd->rd_idle_data.idling_queue_idx);
+					rd->rd_idle_data.idling_queue_idx =
+						ROWQ_MAX_PRIO;
+				}
 			}
 
 			if (row_regular_req_pending(rd) &&
@@ -726,11 +729,12 @@
 	int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx;
 
 	if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) {
-		(void)hrtimer_cancel(&rd->rd_idle_data.hr_timer);
-		row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx,
-			"Canceled delayed work on %d - forced dispatch",
-			rd->rd_idle_data.idling_queue_idx);
-		rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
+		if (hrtimer_try_to_cancel(&rd->rd_idle_data.hr_timer) >= 0) {
+			row_log(rd->dispatch_queue,
+				"Canceled delayed work on %d - forced dispatch",
+				rd->rd_idle_data.idling_queue_idx);
+			rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
+		}
 	}
 
 	if (rd->pending_urgent_rq) {
diff --git a/block/test-iosched.c b/block/test-iosched.c
index b1e5492..07b36b8 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -101,8 +101,8 @@
 		goto exit;
 	}
 
-	ptd->test_info.test_duration = jiffies -
-				ptd->test_info.test_duration;
+	ptd->test_info.test_duration = ktime_sub(ktime_get(),
+				ptd->test_info.test_duration);
 
 	test_pr_info("%s: Test is completed, test_count=%d, reinsert_count=%d,",
 			__func__, ptd->test_count, ptd->reinsert_count);
@@ -774,7 +774,7 @@
 			goto error;
 		}
 
-		ptd->test_info.test_duration = jiffies;
+		ptd->test_info.test_duration = ktime_get();
 		ret = run_test(ptd);
 		if (ret) {
 			test_pr_err("%s: failed to run the test\n", __func__);
@@ -784,10 +784,10 @@
 		test_pr_info("%s: Waiting for the test completion", __func__);
 
 		wait_event(ptd->wait_q, ptd->test_state == TEST_COMPLETED);
-		t_info->test_duration = ptd->test_info.test_duration;
-		t_info->test_byte_count = ptd->test_info.test_byte_count;
 		del_timer_sync(&ptd->timeout_timer);
 
+		memcpy(t_info, &ptd->test_info, sizeof(struct test_info));
+
 		ret = check_test_result(ptd);
 		if (ret) {
 			test_pr_err("%s: check_test_result failed\n",
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 1af9399..d01496e 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -515,6 +515,7 @@
 
 	if (!temp) {
 		pr_err("diag: Invalid buffer in %s\n", __func__);
+		return -ENOMEM;
 	}
 
 	/* This is Pkt request/response transaction */
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 81c5e57..0badda6 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -70,6 +70,17 @@
 		"Modem CMD in_busy_1: %d\n"
 		"Modem CMD in_busy_2: %d\n"
 		"DCI CMD Modem in_busy_1: %d\n"
+		"Modem supports STM: %d\n"
+		"LPASS supports STM: %d\n"
+		"RIVA supports STM: %d\n"
+		"Modem STM state: %d\n"
+		"LPASS STM state: %d\n"
+		"RIVA STM state: %d\n"
+		"APPS STM state: %d\n"
+		"Modem STM requested state: %d\n"
+		"LPASS STM requested state: %d\n"
+		"RIVA STM requested state: %d\n"
+		"APPS STM requested state: %d\n"
 		"logging_mode: %d\n"
 		"real_time_mode: %d\n",
 		(unsigned int)driver->smd_data[MODEM_DATA].ch,
@@ -101,6 +112,17 @@
 		driver->smd_cmd[MODEM_DATA].in_busy_1,
 		driver->smd_cmd[MODEM_DATA].in_busy_2,
 		driver->smd_dci_cmd[MODEM_DATA].in_busy_1,
+		driver->peripheral_supports_stm[MODEM_DATA],
+		driver->peripheral_supports_stm[LPASS_DATA],
+		driver->peripheral_supports_stm[WCNSS_DATA],
+		driver->stm_state[MODEM_DATA],
+		driver->stm_state[LPASS_DATA],
+		driver->stm_state[WCNSS_DATA],
+		driver->stm_state[APPS_DATA],
+		driver->stm_state_requested[MODEM_DATA],
+		driver->stm_state_requested[LPASS_DATA],
+		driver->stm_state_requested[WCNSS_DATA],
+		driver->stm_state_requested[APPS_DATA],
 		driver->logging_mode,
 		driver->real_time_mode);
 
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index d838714..aa1d847 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -26,7 +26,7 @@
 #define ALL_SSID		-1
 #define MAX_SSID_PER_RANGE	100
 
-#define FEATURE_MASK_LEN_BYTES		1
+#define FEATURE_MASK_LEN_BYTES		2
 
 struct mask_info {
 	int equip_id;
@@ -466,7 +466,7 @@
 	void *buf = driver->buf_feature_mask_update;
 	int header_size = sizeof(struct diag_ctrl_feature_mask);
 	int wr_size = -ENOMEM, retry_count = 0;
-	uint8_t feature_byte = 0;
+	uint8_t feature_bytes[FEATURE_MASK_LEN_BYTES] = {0, 0};
 	int total_len = 0;
 
 	if (!smd_info) {
@@ -487,11 +487,12 @@
 	driver->feature_mask->ctrl_pkt_data_len = 4 + FEATURE_MASK_LEN_BYTES;
 	driver->feature_mask->feature_mask_len = FEATURE_MASK_LEN_BYTES;
 	memcpy(buf, driver->feature_mask, header_size);
-	feature_byte |= F_DIAG_INT_FEATURE_MASK;
-	feature_byte |= F_DIAG_LOG_ON_DEMAND_RSP_ON_MASTER;
-	feature_byte |= driver->supports_separate_cmdrsp ?
+	feature_bytes[0] |= F_DIAG_INT_FEATURE_MASK;
+	feature_bytes[0] |= F_DIAG_LOG_ON_DEMAND_RSP_ON_MASTER;
+	feature_bytes[0] |= driver->supports_separate_cmdrsp ?
 				F_DIAG_REQ_RSP_CHANNEL : 0;
-	memcpy(buf+header_size, &feature_byte, FEATURE_MASK_LEN_BYTES);
+	feature_bytes[1] |= F_DIAG_OVER_STM;
+	memcpy(buf+header_size, &feature_bytes, FEATURE_MASK_LEN_BYTES);
 	total_len = header_size + FEATURE_MASK_LEN_BYTES;
 
 	while (retry_count < 3) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 1495ad5..b7784b5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -89,6 +89,13 @@
 #define DIAG_CON_LPASS (0x0004)	/* Bit mask for LPASS */
 #define DIAG_CON_WCNSS (0x0008)	/* Bit mask for WCNSS */
 
+#define NUM_STM_PROCESSORS	4
+
+#define DIAG_STM_MODEM	0x01
+#define DIAG_STM_LPASS	0x02
+#define DIAG_STM_WCNSS	0x04
+#define DIAG_STM_APPS	0x08
+
 /*
  * The status bit masks when received in a signal handler are to be
  * used in conjunction with the peripheral list bit mask to determine the
@@ -230,6 +237,8 @@
 	struct work_struct diag_read_smd_work;
 	struct work_struct diag_notify_update_smd_work;
 	int notify_context;
+	struct work_struct diag_general_smd_work;
+	int general_context;
 
 	/*
 	 * Function ptr for function to call to process the data that
@@ -261,6 +270,12 @@
 	unsigned int buf_tbl_size;
 	int use_device_tree;
 	int supports_separate_cmdrsp;
+	/* The state requested in the STM command */
+	int stm_state_requested[NUM_STM_PROCESSORS];
+	/* The current STM state */
+	int stm_state[NUM_STM_PROCESSORS];
+	/* Whether or not the peripheral supports STM */
+	int peripheral_supports_stm[NUM_SMD_CONTROL_CHANNELS];
 	/* DCI related variables */
 	struct dci_pkt_req_tracking_tbl *req_tracking_tbl;
 	struct diag_dci_client_tbl *dci_client_tbl;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 12c40da..7513c7b 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -44,6 +44,9 @@
 #include "diag_masks.h"
 #include "diagfwd_bridge.h"
 
+#include <linux/coresight-stm.h>
+#include <linux/kernel.h>
+
 MODULE_DESCRIPTION("Diag Char Driver");
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("1.0");
@@ -1797,6 +1800,21 @@
 		ret = -EFAULT;
 		goto fail_free_copy;
 	}
+	if (driver->stm_state[APPS_DATA] &&
+		(pkt_type >= DATA_TYPE_EVENT && pkt_type <= DATA_TYPE_LOG)) {
+		int stm_size = 0;
+
+		stm_size = stm_log_inv_ts(OST_ENTITY_DIAG, 0, buf_copy,
+						payload_size);
+
+		if (stm_size == 0)
+			pr_debug("diag: In %s, stm_log_inv_ts returned size of 0\n",
+				__func__);
+
+		diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+		return 0;
+	}
+
 #ifdef DIAG_DEBUG
 	printk(KERN_DEBUG "data is -->\n");
 	for (i = 0; i < payload_size; i++)
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index d07cc04..6e7080e 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -46,6 +46,16 @@
 #define MODE_CMD		41
 #define RESET_ID		2
 
+#define STM_CMD_VERSION_OFFSET	4
+#define STM_CMD_MASK_OFFSET	5
+#define STM_CMD_DATA_OFFSET	6
+#define STM_CMD_NUM_BYTES	7
+
+#define STM_RSP_VALID_INDEX		7
+#define STM_RSP_SUPPORTED_INDEX		8
+#define STM_RSP_SMD_COMPLY_INDEX	9
+#define STM_RSP_NUM_BYTES		10
+
 int diag_debug_buf_idx;
 unsigned char diag_debug_buf[1024];
 /* Number of entries in table of buffers */
@@ -763,6 +773,77 @@
 	}
 }
 
+void diag_process_stm_mask(uint8_t cmd, uint8_t data_mask, int data_type,
+			  uint8_t *rsp_supported, uint8_t *rsp_smd_comply)
+{
+	int status = 0;
+	if (data_type >= MODEM_DATA && data_type <= WCNSS_DATA) {
+		if (driver->peripheral_supports_stm[data_type]) {
+			status = diag_send_stm_state(
+				&driver->smd_cntl[data_type], cmd);
+			if (status == 1)
+				*rsp_smd_comply |= data_mask;
+			*rsp_supported |= data_mask;
+		} else if (driver->smd_cntl[data_type].ch) {
+			*rsp_smd_comply |= data_mask;
+		}
+		if ((*rsp_smd_comply & data_mask) &&
+			(*rsp_supported & data_mask))
+			driver->stm_state[data_type] = cmd;
+
+		driver->stm_state_requested[data_type] = cmd;
+	} else if (data_type == APPS_DATA) {
+		*rsp_supported |= data_mask;
+		*rsp_smd_comply |= data_mask;
+		driver->stm_state[data_type] = cmd;
+		driver->stm_state_requested[data_type] = cmd;
+	}
+}
+
+int diag_process_stm_cmd(unsigned char *buf)
+{
+	uint8_t version = *(buf+STM_CMD_VERSION_OFFSET);
+	uint8_t mask = *(buf+STM_CMD_MASK_OFFSET);
+	uint8_t cmd = *(buf+STM_CMD_DATA_OFFSET);
+	uint8_t rsp_supported = 0;
+	uint8_t rsp_smd_comply = 0;
+	int valid_command = 1;
+	int i;
+
+	/* Check if command is valid */
+	if ((version != 1) || (mask == 0) || (0 != (mask >> 4)) ||
+			(cmd != ENABLE_STM && cmd != DISABLE_STM)) {
+		valid_command = 0;
+	} else {
+		if (mask & DIAG_STM_MODEM)
+			diag_process_stm_mask(cmd, DIAG_STM_MODEM, MODEM_DATA,
+					&rsp_supported, &rsp_smd_comply);
+
+		if (mask & DIAG_STM_LPASS)
+			diag_process_stm_mask(cmd, DIAG_STM_LPASS, LPASS_DATA,
+					&rsp_supported, &rsp_smd_comply);
+
+		if (mask & DIAG_STM_WCNSS)
+			diag_process_stm_mask(cmd, DIAG_STM_WCNSS, WCNSS_DATA,
+					&rsp_supported, &rsp_smd_comply);
+
+		if (mask & DIAG_STM_APPS)
+			diag_process_stm_mask(cmd, DIAG_STM_APPS, APPS_DATA,
+					&rsp_supported, &rsp_smd_comply);
+	}
+
+	for (i = 0; i < STM_CMD_NUM_BYTES; i++)
+		driver->apps_rsp_buf[i] = *(buf+i);
+
+	driver->apps_rsp_buf[STM_RSP_VALID_INDEX] = valid_command;
+	driver->apps_rsp_buf[STM_RSP_SUPPORTED_INDEX] = rsp_supported;
+	driver->apps_rsp_buf[STM_RSP_SMD_COMPLY_INDEX] = rsp_smd_comply;
+
+	encode_rsp_and_send(STM_RSP_NUM_BYTES-1);
+
+	return 0;
+}
+
 int diag_process_apps_pkt(unsigned char *buf, int len)
 {
 	uint16_t subsys_cmd_code;
@@ -838,6 +919,9 @@
 		*(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
 		encode_rsp_and_send(7);
 		return 0;
+	} else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
+		(*(uint16_t *)(buf+2) == 0x020E)) {
+		return diag_process_stm_cmd(buf);
 	}
 	/* Check for Apps Only & get event mask request */
 	else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only() &&
@@ -1592,6 +1676,9 @@
 			/* Notify the clients of the close */
 			diag_dci_notify_client(smd_info->peripheral_mask,
 							DIAG_STATUS_CLOSED);
+		} else if (smd_info->type == SMD_CNTL_TYPE) {
+			diag_cntl_stm_notify(smd_info,
+						CLEAR_PERIPHERAL_STM_STATE);
 		}
 		return;
 	} else if (event == SMD_EVENT_OPEN) {
@@ -1833,20 +1920,27 @@
 	 * information to the update function.
 	 */
 	smd_info->notify_context = 0;
+	smd_info->general_context = 0;
 	switch (type) {
 	case SMD_DATA_TYPE:
 	case SMD_CMD_TYPE:
 		INIT_WORK(&(smd_info->diag_notify_update_smd_work),
 						diag_clean_reg_fn);
+		INIT_WORK(&(smd_info->diag_general_smd_work),
+						diag_cntl_smd_work_fn);
 		break;
 	case SMD_CNTL_TYPE:
 		INIT_WORK(&(smd_info->diag_notify_update_smd_work),
 						diag_mask_update_fn);
+		INIT_WORK(&(smd_info->diag_general_smd_work),
+						diag_cntl_smd_work_fn);
 		break;
 	case SMD_DCI_TYPE:
 	case SMD_DCI_CMD_TYPE:
 		INIT_WORK(&(smd_info->diag_notify_update_smd_work),
 					diag_update_smd_dci_work_fn);
+		INIT_WORK(&(smd_info->diag_general_smd_work),
+					diag_cntl_smd_work_fn);
 		break;
 	default:
 		pr_err("diag: In %s, unknown type, type: %d\n", __func__, type);
@@ -1931,8 +2025,15 @@
 	mutex_init(&driver->diag_hdlc_mutex);
 	mutex_init(&driver->diag_cntl_mutex);
 
-	for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+	for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 		driver->separate_cmdrsp[i] = 0;
+		driver->peripheral_supports_stm[i] = DISABLE_STM;
+	}
+
+	for (i = 0; i < NUM_STM_PROCESSORS; i++) {
+		driver->stm_state_requested[i] = DISABLE_STM;
+		driver->stm_state[i] = DISABLE_STM;
+	}
 
 	for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
 		success = diag_smd_constructor(&driver->smd_data[i], i,
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index b36b7dd..a832cb3 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -40,6 +40,55 @@
 	smd_info->notify_context = 0;
 }
 
+void diag_cntl_smd_work_fn(struct work_struct *work)
+{
+	struct diag_smd_info *smd_info = container_of(work,
+						struct diag_smd_info,
+						diag_general_smd_work);
+
+	if (!smd_info || smd_info->type != SMD_CNTL_TYPE)
+		return;
+
+	if (smd_info->general_context == UPDATE_PERIPHERAL_STM_STATE) {
+		if (driver->peripheral_supports_stm[smd_info->peripheral] ==
+								ENABLE_STM) {
+			int status = 0;
+			int index = smd_info->peripheral;
+			status = diag_send_stm_state(smd_info,
+				(uint8_t)(driver->stm_state_requested[index]));
+			if (status == 1)
+				driver->stm_state[index] =
+					driver->stm_state_requested[index];
+		}
+	}
+	smd_info->general_context = 0;
+}
+
+void diag_cntl_stm_notify(struct diag_smd_info *smd_info, int action)
+{
+	if (!smd_info || smd_info->type != SMD_CNTL_TYPE)
+		return;
+
+	if (action == CLEAR_PERIPHERAL_STM_STATE)
+		driver->peripheral_supports_stm[smd_info->peripheral] =
+								DISABLE_STM;
+}
+
+static void process_stm_feature(struct diag_smd_info *smd_info,
+			      uint8_t feature_mask)
+{
+	if (feature_mask & F_DIAG_OVER_STM) {
+		driver->peripheral_supports_stm[smd_info->peripheral] =
+								ENABLE_STM;
+		smd_info->general_context = UPDATE_PERIPHERAL_STM_STATE;
+		queue_work(driver->diag_cntl_wq,
+				&(smd_info->diag_general_smd_work));
+	} else {
+		driver->peripheral_supports_stm[smd_info->peripheral] =
+								DISABLE_STM;
+	}
+}
+
 /* Process the data read from the smd control channel */
 int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
 								int total_recd)
@@ -120,8 +169,9 @@
 			uint8_t feature_mask = 0;
 			int feature_mask_len = *(int *)(buf+8);
 			if (feature_mask_len > 0) {
+				int periph = smd_info->peripheral;
 				feature_mask = *(uint8_t *)(buf+12);
-				if (smd_info->peripheral == MODEM_DATA)
+				if (periph == MODEM_DATA)
 					driver->log_on_demand_support =
 						feature_mask &
 					F_DIAG_LOG_ON_DEMAND_RSP_ON_MASTER;
@@ -132,13 +182,16 @@
 				 */
 				if (driver->supports_separate_cmdrsp &&
 					(feature_mask & F_DIAG_REQ_RSP_CHANNEL))
-					driver->separate_cmdrsp
-						[smd_info->peripheral] =
+					driver->separate_cmdrsp[periph] =
 							ENABLE_SEPARATE_CMDRSP;
 				else
-					driver->separate_cmdrsp
-						[smd_info->peripheral] =
+					driver->separate_cmdrsp[periph] =
 							DISABLE_SEPARATE_CMDRSP;
+				if (feature_mask_len > 1) {
+					feature_mask = *(uint8_t *)(buf+13);
+					process_stm_feature(smd_info,
+								feature_mask);
+				}
 			}
 			flag = 1;
 		} else if (type != DIAG_CTRL_MSG_REG) {
@@ -298,6 +351,56 @@
 	mutex_unlock(&driver->diag_cntl_mutex);
 }
 
+int diag_send_stm_state(struct diag_smd_info *smd_info,
+			  uint8_t stm_control_data)
+{
+	struct diag_ctrl_msg_stm stm_msg;
+	int msg_size = sizeof(struct diag_ctrl_msg_stm);
+	int retry_count = 0;
+	int wr_size = 0;
+	int success = 0;
+
+	if (!smd_info || (smd_info->type != SMD_CNTL_TYPE) ||
+		(driver->peripheral_supports_stm[smd_info->peripheral] ==
+								DISABLE_STM)) {
+		return -EINVAL;
+	}
+
+	if (smd_info->ch) {
+		stm_msg.ctrl_pkt_id = 21;
+		stm_msg.ctrl_pkt_data_len = 5;
+		stm_msg.version = 1;
+		stm_msg.control_data = stm_control_data;
+		while (retry_count < 3) {
+			wr_size = smd_write(smd_info->ch, &stm_msg, msg_size);
+			if (wr_size == -ENOMEM) {
+				/*
+				 * The smd channel is full. Delay while
+				 * smd processes existing data and smd
+				 * has memory become available. The delay
+				 * of 10000 was determined empirically as
+				 * best value to use.
+				 */
+				retry_count++;
+				usleep_range(10000, 10000);
+			} else {
+				success = 1;
+				break;
+			}
+		}
+		if (wr_size != msg_size) {
+			pr_err("diag: In %s, proc %d fail STM update %d, tried %d",
+				__func__, smd_info->peripheral, wr_size,
+				msg_size);
+			success = 0;
+		}
+	} else {
+		pr_err("diag: In %s, ch invalid, STM update on proc %d\n",
+				__func__, smd_info->peripheral);
+	}
+	return success;
+}
+
 static int diag_smd_cntl_probe(struct platform_device *pdev)
 {
 	int r = 0;
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index ddefe10..c90c132 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -45,10 +45,18 @@
  * new Data Rx and DCI Rx channels
  */
 #define F_DIAG_REQ_RSP_CHANNEL		0x10
+/* Denotes we support diag over stm */
+#define F_DIAG_OVER_STM			0x02
 
 #define ENABLE_SEPARATE_CMDRSP	1
 #define DISABLE_SEPARATE_CMDRSP	0
 
+#define ENABLE_STM	1
+#define DISABLE_STM	0
+
+#define UPDATE_PERIPHERAL_STM_STATE	1
+#define CLEAR_PERIPHERAL_STM_STATE	2
+
 struct cmd_code_range {
 	uint16_t cmd_code_lo;
 	uint16_t cmd_code_hi;
@@ -117,11 +125,19 @@
 	uint32_t event_stale_timer_val;
 } __packed;
 
+struct diag_ctrl_msg_stm {
+	uint32_t ctrl_pkt_id;
+	uint32_t ctrl_pkt_data_len;
+	uint32_t version;
+	uint8_t  control_data;
+} __packed;
+
 void diagfwd_cntl_init(void);
 void diagfwd_cntl_exit(void);
 void diag_read_smd_cntl_work_fn(struct work_struct *);
 void diag_notify_ctrl_update_fn(struct work_struct *work);
 void diag_clean_reg_fn(struct work_struct *work);
+void diag_cntl_smd_work_fn(struct work_struct *work);
 int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
 								int total_recd);
 void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
@@ -129,4 +145,8 @@
 void diag_update_proc_vote(uint16_t proc, uint8_t vote);
 void diag_update_real_time_vote(uint16_t proc, uint8_t real_time);
 void diag_real_time_work_fn(struct work_struct *work);
+int diag_send_stm_state(struct diag_smd_info *smd_info,
+				uint8_t stm_control_data);
+void diag_cntl_stm_notify(struct diag_smd_info *smd_info, int action);
+
 #endif
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index f22b4c2..a6ef3ca 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -151,8 +151,9 @@
 		if (diag_hsic[index].diag_hsic_pool &&
 				(diag_hsic[index].hsic_inited == 0)) {
 			if (diag_hsic[index].count_hsic_pool == 0) {
-				mempool_destroy(driver->diag_hdlc_pool);
-				driver->diag_hdlc_pool = NULL;
+				mempool_destroy(
+					diag_hsic[index].diag_hsic_pool);
+				diag_hsic[index].diag_hsic_pool = NULL;
 			} else if (pool_type == POOL_TYPE_ALL)
 				pr_err("Unable to destroy HDLC mempool for ch %d"
 								, index);
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 085f721..81672ea 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -450,6 +450,8 @@
 
 static int stm_send(void *addr, const void *data, uint32_t size)
 {
+	uint32_t len = size;
+
 	if (((unsigned long)data & 0x1) && (size >= 1)) {
 		stm_data_writeb(*(uint8_t *)data, addr);
 		data++;
@@ -479,7 +481,7 @@
 		size--;
 	}
 
-	return size;
+	return len;
 }
 
 static int stm_trace_ost_header(unsigned long ch_addr, uint32_t options,
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 2fd8bef..96e759b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -610,6 +610,9 @@
 				if (dbs_info->cur_policy) {
 					/* restart dbs timer */
 					dbs_timer_init(dbs_info);
+					/* Enable frequency synchronization
+					 * of CPUs */
+					atomic_set(&dbs_info->sync_enabled, 1);
 				}
 skip_this_cpu:
 				unlock_policy_rwsem_write(cpu);
@@ -639,15 +642,19 @@
 
 			if (dbs_info->cur_policy) {
 				/* cpu using ondemand, cancel dbs timer */
-				mutex_lock(&dbs_info->timer_mutex);
 				dbs_timer_exit(dbs_info);
+				/* Disable frequency synchronization of
+				 * CPUs to avoid re-queueing of work from
+				 * sync_thread */
+				atomic_set(&dbs_info->sync_enabled, 0);
 
+				mutex_lock(&dbs_info->timer_mutex);
 				ondemand_powersave_bias_setspeed(
 					dbs_info->cur_policy,
 					NULL,
 					input);
-
 				mutex_unlock(&dbs_info->timer_mutex);
+
 			}
 skip_this_cpu_bypass:
 			unlock_policy_rwsem_write(cpu);
@@ -1075,18 +1082,6 @@
 
 		get_online_cpus();
 
-		/* TODO: cur_policy is currently set for all CPUs when
-		 * a policy is started but cleared only on the current
-		 * CPU when the policy is stopped. If/when this is
-		 * resolved, sync_enabled can be removed and
-		 * cur_policy can be used instead.
-		 */
-		if (!atomic_read(&this_dbs_info->sync_enabled)) {
-			atomic_set(&this_dbs_info->src_sync_cpu, -1);
-			put_online_cpus();
-			continue;
-		}
-
 		src_cpu = atomic_read(&this_dbs_info->src_sync_cpu);
 		src_dbs_info = &per_cpu(od_cpu_dbs_info, src_cpu);
 		if (src_dbs_info != NULL &&
@@ -1101,6 +1096,13 @@
 		if (lock_policy_rwsem_write(cpu) < 0)
 			goto bail_acq_sema_failed;
 
+		if (!atomic_read(&this_dbs_info->sync_enabled)) {
+			atomic_set(&this_dbs_info->src_sync_cpu, -1);
+			put_online_cpus();
+			unlock_policy_rwsem_write(cpu);
+			continue;
+		}
+
 		policy = this_dbs_info->cur_policy;
 		if (!policy) {
 			/* CPU not using ondemand governor */
@@ -1238,7 +1240,8 @@
 						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 			set_cpus_allowed(j_dbs_info->sync_thread,
 					 *cpumask_of(j));
-			atomic_set(&j_dbs_info->sync_enabled, 1);
+			if (!dbs_tuners_ins.powersave_bias)
+				atomic_set(&j_dbs_info->sync_enabled, 1);
 		}
 		this_dbs_info->cpu = cpu;
 		this_dbs_info->rate_mult = 1;
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index f1868a8..f2f4fad 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -203,8 +203,7 @@
 }
 
 /**
- * Protects memory if heap is unsecured heap. Also ensures that we are in
- * the correct FMEM state if this heap is a reusable heap.
+ * Protects memory if heap is unsecured heap.
  * Must be called with heap->lock locked.
  */
 static int ion_cp_protect(struct ion_heap *heap, int version, void *data)
@@ -244,8 +243,7 @@
 }
 
 /**
- * Unprotects memory if heap is secure heap. Also ensures that we are in
- * the correct FMEM state if this heap is a reusable heap.
+ * Unprotects memory if heap is secure heap.
  * Must be called with heap->lock locked.
  */
 static void ion_cp_unprotect(struct ion_heap *heap, int version, void *data)
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 4e3af1c..f990ada 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -17,7 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/memory_alloc.h>
-#include <linux/fmem.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mm.h>
@@ -422,22 +421,9 @@
 			    struct ion_co_heap_pdata *co_heap_data,
 			    struct ion_cp_heap_pdata *cp_data)
 {
-	if (cp_data->reusable) {
-		const struct fmem_data *fmem_info = fmem_get_info();
-
-		if (!fmem_info) {
-			pr_err("fmem info pointer NULL!\n");
-			BUG();
-		}
-
-		heap->base = fmem_info->phys - fmem_info->reserved_size_low;
-		cp_data->virt_addr = fmem_info->virt;
-		pr_info("ION heap %s using FMEM\n", shared_heap->name);
-	} else {
-		heap->base = msm_ion_get_base(heap->size + shared_heap->size,
-						shared_heap->memory_type,
-						co_heap_data->align);
-	}
+	heap->base = msm_ion_get_base(heap->size + shared_heap->size,
+					shared_heap->memory_type,
+					co_heap_data->align);
 	if (heap->base) {
 		shared_heap->base = heap->base + heap->size;
 		cp_data->secure_base = heap->base;
@@ -463,15 +449,6 @@
 			struct ion_cp_heap_pdata *cp_data =
 			   (struct ion_cp_heap_pdata *) shared_heap->extra_data;
 			if (cp_data->fixed_position == FIXED_MIDDLE) {
-				const struct fmem_data *fmem_info =
-					fmem_get_info();
-
-				if (!fmem_info) {
-					pr_err("fmem info pointer NULL!\n");
-					BUG();
-				}
-
-				cp_data->virt_addr = fmem_info->virt;
 				if (!cp_data->secure_base) {
 					cp_data->secure_base = heap->base;
 					cp_data->secure_size =
@@ -523,17 +500,6 @@
 			struct ion_cp_heap_pdata *data =
 				(struct ion_cp_heap_pdata *)
 				heap->extra_data;
-			if (data->reusable) {
-				const struct fmem_data *fmem_info =
-					fmem_get_info();
-				heap->base = fmem_info->phys;
-				data->virt_addr = fmem_info->virt;
-				pr_info("ION heap %s using FMEM\n", heap->name);
-			} else if (data->mem_is_fmem) {
-				const struct fmem_data *fmem_info =
-					fmem_get_info();
-				heap->base = fmem_info->phys + fmem_info->size;
-			}
 			align = data->align;
 			break;
 		}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 95eabcd..afb11c2 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -841,12 +841,10 @@
 	}
 	num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu);
 
-	context = idr_find(&device->context_idr, context_id);
+	context = kgsl_context_get(device, context_id);
 	if (context == NULL)
 		return;
 
-	kgsl_context_get(context);
-
 	adreno_ctx = context->devctxt;
 
 	if (kgsl_mmu_enable_clk(&device->mmu,
@@ -890,7 +888,6 @@
 
 	kgsl_mmu_disable_clk_on_ts(&device->mmu,
 		rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
-
 	kgsl_context_put(context);
 }
 
@@ -919,7 +916,7 @@
 	 * easier to filter out the mmu accesses from the dump
 	 */
 	if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
-		context = idr_find(&device->context_idr, context_id);
+		context = kgsl_context_get(device, context_id);
 		if (context == NULL)
 			return;
 		adreno_ctx = context->devctxt;
@@ -999,6 +996,8 @@
 		adreno_ringbuffer_issuecmds(device, adreno_ctx,
 					KGSL_CMD_FLAGS_PMODE,
 					&link[0], sizedwords);
+
+		kgsl_context_put(context);
 	} else {
 		kgsl_mmu_device_setstate(&device->mmu, flags);
 	}
@@ -1869,59 +1868,79 @@
 	return 0;
 }
 
+/*
+ * Set the reset status of all contexts to
+ * INNOCENT_CONTEXT_RESET_EXT except for the bad context
+ * since thats the guilty party, if fault tolerance failed then
+ * mark all as guilty
+ */
+
+static int _mark_context_status(int id, void *ptr, void *data)
+{
+	unsigned int ft_status = *((unsigned int *) data);
+	struct kgsl_context *context = ptr;
+	struct adreno_context *adreno_context = context->devctxt;
+
+	if (ft_status) {
+		context->reset_status =
+				KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+		adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
+	} else if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
+		context->reset_status) {
+		if (adreno_context->flags & (CTXT_FLAGS_GPU_HANG |
+			CTXT_FLAGS_GPU_HANG_FT))
+			context->reset_status =
+			KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+		else
+			context->reset_status =
+			KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
+	}
+
+	return 0;
+}
+
 static void adreno_mark_context_status(struct kgsl_device *device,
 					int ft_status)
 {
-	struct kgsl_context *context;
-	int next = 0;
-	/*
-	 * Set the reset status of all contexts to
-	 * INNOCENT_CONTEXT_RESET_EXT except for the bad context
-	 * since thats the guilty party, if fault tolerance failed then
-	 * mark all as guilty
-	 */
-	while ((context = idr_get_next(&device->context_idr, &next))) {
-		struct adreno_context *adreno_context = context->devctxt;
-		if (ft_status) {
-			context->reset_status =
-					KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
-			adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
-		} else if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
-			context->reset_status) {
-			if (adreno_context->flags & (CTXT_FLAGS_GPU_HANG |
-				CTXT_FLAGS_GPU_HANG_FT))
-				context->reset_status =
-				KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
-			else
-				context->reset_status =
-				KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
-		}
-		next = next + 1;
+	/* Mark the status for all the contexts in the device */
+
+	read_lock(&device->context_lock);
+	idr_for_each(&device->context_idr, _mark_context_status, &ft_status);
+	read_unlock(&device->context_lock);
+}
+
+/*
+ * For hung contexts set the current memstore value to the most recent issued
+ * timestamp - this resets the status and lets the system continue on
+ */
+
+static int _set_max_ts(int id, void *ptr, void *data)
+{
+	struct kgsl_device *device = data;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+	struct kgsl_context *context = ptr;
+	struct adreno_context *drawctxt = context->devctxt;
+
+	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
+		kgsl_sharedmem_writel(device, &device->memstore,
+			KGSL_MEMSTORE_OFFSET(context->id,
+			soptimestamp),
+			rb->timestamp[context->id]);
+		kgsl_sharedmem_writel(device, &device->memstore,
+			KGSL_MEMSTORE_OFFSET(context->id,
+			eoptimestamp),
+			rb->timestamp[context->id]);
 	}
+
+	return 0;
 }
 
 static void adreno_set_max_ts_for_bad_ctxs(struct kgsl_device *device)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	struct kgsl_context *context;
-	struct adreno_context *temp_adreno_context;
-	int next = 0;
-
-	while ((context = idr_get_next(&device->context_idr, &next))) {
-		temp_adreno_context = context->devctxt;
-		if (temp_adreno_context->flags & CTXT_FLAGS_GPU_HANG) {
-			kgsl_sharedmem_writel(device, &device->memstore,
-				KGSL_MEMSTORE_OFFSET(context->id,
-				soptimestamp),
-				rb->timestamp[context->id]);
-			kgsl_sharedmem_writel(device, &device->memstore,
-				KGSL_MEMSTORE_OFFSET(context->id,
-				eoptimestamp),
-				rb->timestamp[context->id]);
-		}
-		next = next + 1;
-	}
+	read_lock(&device->context_lock);
+	idr_for_each(&device->context_idr, _set_max_ts, device);
+	read_unlock(&device->context_lock);
 }
 
 static void adreno_destroy_ft_data(struct adreno_ft_data *ft_data)
@@ -2148,7 +2167,7 @@
 	ft_data->status = 0;
 
 	/* find the start of bad command sequence in rb */
-	context = idr_find(&device->context_idr, ft_data->context_id);
+	context = kgsl_context_get(device, ft_data->context_id);
 
 	ft_data->ft_policy = adreno_dev->ft_policy;
 
@@ -2160,7 +2179,7 @@
 					ft_data->global_eop + 1, false);
 	if (ret) {
 		ft_data->ft_policy |= KGSL_FT_TEMP_DISABLE;
-		return;
+		goto done;
 	} else {
 		ft_data->start_of_replay_cmds = rb_rptr;
 		ft_data->ft_policy &= ~KGSL_FT_TEMP_DISABLE;
@@ -2175,14 +2194,16 @@
 				if (ret) {
 					KGSL_FT_ERR(device,
 					"Start not found for replay IB seq\n");
-					ret = 0;
-					return;
+					goto done;
 				}
 				ft_data->start_of_replay_cmds = rb_rptr;
 				ft_data->replay_for_snapshot = rb_rptr;
 			}
 		}
 	}
+
+done:
+	kgsl_context_put(context);
 }
 
 static int
@@ -2402,7 +2423,8 @@
 	static int no_context_ft;
 	struct kgsl_mmu *mmu = &device->mmu;
 
-	context = idr_find(&device->context_idr, ft_data->context_id);
+	context = kgsl_context_get(device, ft_data->context_id);
+
 	if (context == NULL) {
 		KGSL_FT_ERR(device, "Last context unknown id:%d\n",
 			ft_data->context_id);
@@ -2593,17 +2615,21 @@
 	/* ringbuffer now has data from the last valid context id,
 	 * so restore the active_ctx to the last valid context */
 	if (ft_data->last_valid_ctx_id) {
-		struct kgsl_context *last_ctx =
-				idr_find(&device->context_idr,
-				ft_data->last_valid_ctx_id);
+		struct kgsl_context *last_ctx = kgsl_context_get(device,
+			ft_data->last_valid_ctx_id);
+
 		if (last_ctx)
 			adreno_dev->drawctxt_active = last_ctx->devctxt;
+
+		kgsl_context_put(last_ctx);
 	}
 
 done:
 	/* Turn off iommu clocks */
 	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
 		kgsl_mmu_disable_clk_on_ts(&device->mmu, 0, false);
+
+	kgsl_context_put(context);
 	return ret;
 }
 
@@ -3072,7 +3098,10 @@
 	struct kgsl_context *context;
 	struct adreno_context *adreno_context = NULL;
 	int next = 0;
+	struct kgsl_memdesc *desc = NULL;
 
+
+	read_lock(&device->context_lock);
 	while (1) {
 		context = idr_get_next(&device->context_idr, &next);
 		if (context == NULL)
@@ -3082,20 +3111,19 @@
 
 		if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
 					pt_base)) {
-			struct kgsl_memdesc *desc;
-
 			desc = &adreno_context->gpustate;
 			if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
-				return desc;
+				break;
 
 			desc = &adreno_context->context_gmem_shadow.gmemshadow;
 			if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
-				return desc;
+				break;
 		}
 		next = next + 1;
+		desc = NULL;
 	}
-
-	return NULL;
+	read_unlock(&device->context_lock);
+	return desc;
 }
 
 struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
@@ -3420,8 +3448,8 @@
 				current_context));
 			/* Make sure the memstore read has posted */
 			mb();
-			context = idr_find(&device->context_idr,
-				curr_context_id);
+
+			context = kgsl_context_get(device, curr_context_id);
 			if (context != NULL) {
 				curr_context = context->devctxt;
 				curr_context->ib_gpu_time_used = 0;
@@ -3497,6 +3525,7 @@
 	} else {
 		/* GPU is moving forward */
 		prev_global_ts = curr_global_ts;
+		kgsl_context_put(context);
 		context = NULL;
 		curr_context = NULL;
 		adreno_dev->long_ib = 0;
@@ -3737,7 +3766,8 @@
 
 		binbase = data;
 
-		context = kgsl_find_context(dev_priv, binbase->drawctxt_id);
+		context = kgsl_context_get_owner(dev_priv,
+			binbase->drawctxt_id);
 		if (context) {
 			adreno_drawctxt_set_bin_base_offset(
 				device, context, binbase->offset);
@@ -3748,6 +3778,8 @@
 				"device_id=%d\n",
 				binbase->drawctxt_id, device->id);
 		}
+
+		kgsl_context_put(context);
 		break;
 	}
 	case IOCTL_KGSL_PERFCOUNTER_GET: {
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index ebfd837..7a070a6 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -473,7 +473,9 @@
 			(unsigned int *) &context_id,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 				current_context));
-	context = idr_find(&device->context_idr, context_id);
+
+	context = kgsl_context_get(device, context_id);
+
 	if (context) {
 		ts_processed = kgsl_readtimestamp(device, context,
 						  KGSL_TIMESTAMP_RETIRED);
@@ -482,6 +484,8 @@
 	} else
 		KGSL_LOG_DUMP(device, "BAD CTXT: %d\n", context_id);
 
+	kgsl_context_put(context);
+
 	num_item = adreno_ringbuffer_count(&adreno_dev->ringbuffer,
 						cp_rb_rptr);
 	if (num_item <= 0)
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index fcef296..f6c05b5 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1279,11 +1279,13 @@
 	if (0xFFFFFFFF == ft_data->start_of_replay_cmds)
 		return;
 
-	k_ctxt = idr_find(&device->context_idr, ft_data->context_id);
+	k_ctxt = kgsl_context_get(device, ft_data->context_id);
+
 	if (k_ctxt) {
 		a_ctxt = k_ctxt->devctxt;
 		if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
 			_turn_preamble_on_for_ib_seq(rb, rb_rptr);
+		kgsl_context_put(k_ctxt);
 	}
 	k_ctxt = NULL;
 
@@ -1314,7 +1316,8 @@
 			/* if context switches to a context that did not cause
 			 * hang then start saving the rb contents as those
 			 * commands can be executed */
-			k_ctxt = idr_find(&rb->device->context_idr, val2);
+			k_ctxt = kgsl_context_get(rb->device, val2);
+
 			if (k_ctxt) {
 				a_ctxt = k_ctxt->devctxt;
 
@@ -1352,6 +1355,7 @@
 				copy_rb_contents = 0;
 			}
 			}
+			kgsl_context_put(k_ctxt);
 		}
 
 		if (copy_rb_contents)
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 5c454f1..4c1ef54 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -453,28 +453,27 @@
 static struct kgsl_context *
 kgsl_create_context(struct kgsl_device_private *dev_priv)
 {
+	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_context *context;
-	int ret, id;
+	int ret, id = 0;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 
-	if (context == NULL) {
-		KGSL_DRV_INFO(dev_priv->device, "kzalloc(%d) failed\n",
-				sizeof(*context));
+	if (context == NULL)
 		return ERR_PTR(-ENOMEM);
-	}
+
 
 	while (1) {
-		if (idr_pre_get(&dev_priv->device->context_idr,
-				GFP_KERNEL) == 0) {
-			KGSL_DRV_INFO(dev_priv->device,
-					"idr_pre_get: ENOMEM\n");
+		if (idr_pre_get(&device->context_idr, GFP_KERNEL) == 0) {
+			KGSL_DRV_INFO(device, "idr_pre_get: ENOMEM\n");
 			ret = -ENOMEM;
-			goto func_end;
+			break;
 		}
 
-		ret = idr_get_new_above(&dev_priv->device->context_idr,
-				  context, 1, &id);
+		write_lock(&device->context_lock);
+		ret = idr_get_new_above(&device->context_idr, context, 1, &id);
+		context->id = id;
+		write_unlock(&device->context_lock);
 
 		if (ret != -EAGAIN)
 			break;
@@ -485,21 +484,24 @@
 
 	/* MAX - 1, there is one memdesc in memstore for device info */
 	if (id >= KGSL_MEMSTORE_MAX) {
-		KGSL_DRV_INFO(dev_priv->device, "cannot have more than %d "
+		KGSL_DRV_INFO(device, "cannot have more than %d "
 				"ctxts due to memstore limitation\n",
 				KGSL_MEMSTORE_MAX);
-		idr_remove(&dev_priv->device->context_idr, id);
+		write_lock(&device->context_lock);
+		idr_remove(&device->context_idr, id);
+		write_unlock(&device->context_lock);
 		ret = -ENOSPC;
 		goto func_end;
 	}
 
 	kref_init(&context->refcount);
-	context->id = id;
 	context->dev_priv = dev_priv;
 
 	ret = kgsl_sync_timeline_create(context);
 	if (ret) {
+		write_lock(&device->context_lock);
 		idr_remove(&dev_priv->device->context_idr, id);
+		write_unlock(&device->context_lock);
 		goto func_end;
 	}
 
@@ -557,8 +559,14 @@
 	 * it is still in use by the GPU.
 	 */
 	kgsl_cancel_events_ctxt(device, context);
-	idr_remove(&device->context_idr, id);
+
+	write_lock(&device->context_lock);
 	context->id = KGSL_CONTEXT_INVALID;
+	idr_remove(&device->context_idr, id);
+	write_unlock(&device->context_lock);
+
+	context->dev_priv = NULL;
+
 	kgsl_context_put(context);
 }
 
@@ -960,14 +968,15 @@
 	kgsl_active_count_get(device);
 
 	while (1) {
+		read_lock(&device->context_lock);
 		context = idr_get_next(&device->context_idr, &next);
+		read_unlock(&device->context_lock);
+
 		if (context == NULL)
 			break;
 
-		if (context->dev_priv == dev_priv) {
+		if (context->dev_priv == dev_priv)
 			kgsl_context_detach(context);
-			context->dev_priv = NULL;
-		}
 
 		next = next + 1;
 	}
@@ -1309,7 +1318,7 @@
 			result = -EFAULT;
 			break;
 		}
-		context = kgsl_find_context(dev_priv, id);
+		context = kgsl_context_get_owner(dev_priv, id);
 		if (!context) {
 			result = -EINVAL;
 			break;
@@ -1319,12 +1328,14 @@
 		 * the out parameter
 		 */
 		if (copy_to_user(param->value, &(context->reset_status),
-			sizeof(unsigned int))) {
+			sizeof(unsigned int)))
 			result = -EFAULT;
-			break;
+		else {
+			/* Clear reset status once its been queried */
+			context->reset_status = KGSL_CTX_STAT_NO_ERROR;
 		}
-		/* Clear reset status once its been queried */
-		context->reset_status = KGSL_CTX_STAT_NO_ERROR;
+
+		kgsl_context_put(context);
 		break;
 	}
 	default:
@@ -1393,19 +1404,14 @@
 {
 	struct kgsl_device_waittimestamp_ctxtid *param = data;
 	struct kgsl_context *context;
-	int result;
+	long result = -EINVAL;
 
-	context = kgsl_find_context(dev_priv, param->context_id);
-	if (context == NULL)
-		return -EINVAL;
-	/*
-	 * A reference count is needed here, because waittimestamp may
-	 * block with the device mutex unlocked and userspace could
-	 * request for the context to be destroyed during that time.
-	 */
-	kgsl_context_get(context);
-	result = _device_waittimestamp(dev_priv, context,
+	context = kgsl_context_get_owner(dev_priv, param->context_id);
+
+	if (context)
+		result = _device_waittimestamp(dev_priv, context,
 			param->timestamp, param->timeout);
+
 	kgsl_context_put(context);
 	return result;
 }
@@ -1419,7 +1425,7 @@
 	struct kgsl_ibdesc *ibdesc;
 	struct kgsl_context *context;
 
-	context = kgsl_find_context(dev_priv, param->drawctxt_id);
+	context = kgsl_context_get_owner(dev_priv, param->drawctxt_id);
 	if (context == NULL) {
 		result = -EINVAL;
 		goto done;
@@ -1498,7 +1504,7 @@
 free_ibdesc:
 	kfree(ibdesc);
 done:
-
+	kgsl_context_put(context);
 	return result;
 }
 
@@ -1531,13 +1537,16 @@
 {
 	struct kgsl_cmdstream_readtimestamp_ctxtid *param = data;
 	struct kgsl_context *context;
+	long result = -EINVAL;
 
-	context = kgsl_find_context(dev_priv, param->context_id);
-	if (context == NULL)
-		return -EINVAL;
+	context = kgsl_context_get_owner(dev_priv, param->context_id);
 
-	return _cmdstream_readtimestamp(dev_priv, context,
+	if (context)
+		result = _cmdstream_readtimestamp(dev_priv, context,
 			param->type, &param->timestamp);
+
+	kgsl_context_put(context);
+	return result;
 }
 
 static void kgsl_freemem_event_cb(struct kgsl_device *device,
@@ -1598,13 +1607,14 @@
 {
 	struct kgsl_cmdstream_freememontimestamp_ctxtid *param = data;
 	struct kgsl_context *context;
+	long result = -EINVAL;
 
-	context = kgsl_find_context(dev_priv, param->context_id);
-	if (context == NULL)
-		return -EINVAL;
-
-	return _cmdstream_freememontimestamp(dev_priv, param->gpuaddr,
+	context = kgsl_context_get_owner(dev_priv, param->context_id);
+	if (context)
+		result = _cmdstream_freememontimestamp(dev_priv, param->gpuaddr,
 			context, param->timestamp, param->type);
+	kgsl_context_put(context);
+	return result;
 }
 
 static long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv,
@@ -1640,19 +1650,18 @@
 static long kgsl_ioctl_drawctxt_destroy(struct kgsl_device_private *dev_priv,
 					unsigned int cmd, void *data)
 {
-	int result = 0;
 	struct kgsl_drawctxt_destroy *param = data;
 	struct kgsl_context *context;
+	long result = -EINVAL;
 
-	context = kgsl_find_context(dev_priv, param->drawctxt_id);
+	context = kgsl_context_get_owner(dev_priv, param->drawctxt_id);
 
-	if (context == NULL) {
-		result = -EINVAL;
-		goto done;
+	if (context) {
+		kgsl_context_detach(context);
+		result = 0;
 	}
 
-	kgsl_context_detach(context);
-done:
+	kgsl_context_put(context);
 	return result;
 }
 
@@ -3430,6 +3439,8 @@
 		device->id, device->reg_phys, device->reg_len,
 		device->reg_virt);
 
+	rwlock_init(&device->context_lock);
+
 	result = kgsl_drm_init(pdev);
 	if (result)
 		goto error_pwrctrl_close;
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index 641348e..ab5a345 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -14,13 +14,15 @@
 #ifndef __KGSL_CFFDUMP_H
 #define __KGSL_CFFDUMP_H
 
-extern unsigned int kgsl_cff_dump_enable;
-
-#ifdef CONFIG_MSM_KGSL_CFF_DUMP
-
 #include <linux/types.h>
 
-#include "kgsl_device.h"
+extern unsigned int kgsl_cff_dump_enable;
+
+static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; }
+
+struct kgsl_device_private;
+
+#ifdef CONFIG_MSM_KGSL_CFF_DUMP
 
 void kgsl_cffdump_init(void);
 void kgsl_cffdump_destroy(void);
@@ -42,7 +44,6 @@
 		unsigned int cff_opcode, unsigned int op1,
 		unsigned int op2, unsigned int op3,
 		unsigned int op4, unsigned int op5);
-static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; }
 
 void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base,
 			      unsigned int range, unsigned int gmemsize);
@@ -53,20 +54,69 @@
 
 #else
 
-#define kgsl_cffdump_init()					(void)0
-#define kgsl_cffdump_destroy()					(void)0
-#define kgsl_cffdump_open(device)				(void)0
-#define kgsl_cffdump_close(device)				(void)0
-#define kgsl_cffdump_syncmem(dev_priv, memdesc, addr, sizebytes, clean_cache) \
-	(void) 0
-#define kgsl_cffdump_setmem(device, addr, value, sizebytes)	(void)0
-#define kgsl_cffdump_regwrite(device, addr, value)		(void)0
-#define kgsl_cffdump_regpoll(device, addr, value, mask)	(void)0
-#define kgsl_cffdump_parse_ibs(dev_priv, memdesc, gpuaddr, \
-	sizedwords, check_only)					true
-#define kgsl_cffdump_flags_no_memzero()				true
-#define kgsl_cffdump_memory_base(davice, base, range, gmemsize)	(void)0
-#define kgsl_cffdump_hang(device)				(void)0
+static inline void kgsl_cffdump_init(void)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_destroy(void)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_open(struct kgsl_device *device)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_close(struct kgsl_device *device)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+		struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
+		bool clean_cache)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
+		uint value, uint sizebytes)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr,
+					 uint value)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr,
+		uint value, uint mask)
+{
+	return;
+}
+
+static inline bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv,
+	const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords,
+	bool check_only)
+{
+	return false;
+}
+
+static inline void kgsl_cffdump_memory_base(struct kgsl_device *device,
+		unsigned int base, unsigned int range, unsigned int gmemsize)
+{
+	return;
+}
+
+static inline void kgsl_cffdump_hang(struct kgsl_device *device)
+{
+	return;
+}
+
 static inline void kgsl_cffdump_user_event(struct kgsl_device *device,
 		unsigned int cff_opcode, unsigned int op1,
 		unsigned int op2, unsigned int op3,
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2af5ccd..d0e40db 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -191,6 +191,7 @@
 	struct completion ft_gate;
 	struct dentry *d_debugfs;
 	struct idr context_idr;
+	rwlock_t context_lock;
 
 	void *snapshot;		/* Pointer to the snapshot memory region */
 	int snapshot_maxsize;   /* Max size of the snapshot region */
@@ -402,17 +403,7 @@
 	return 0;
 }
 
-static inline struct kgsl_context *
-kgsl_find_context(struct kgsl_device_private *dev_priv, uint32_t id)
-{
-	struct kgsl_context *ctxt =
-		idr_find(&dev_priv->device->context_idr, id);
 
-	/* Make sure that the context belongs to the current instance so
-	   that other processes can't guess context IDs and mess things up */
-
-	return  (ctxt && ctxt->dev_priv == dev_priv) ? ctxt : NULL;
-}
 
 int kgsl_check_timestamp(struct kgsl_device *device,
 		struct kgsl_context *context, unsigned int timestamp);
@@ -436,32 +427,75 @@
 	return pdev->dev.platform_data;
 }
 
-/**
- * kgsl_context_get - Get context reference count
- * @context
- *
- * Asynchronous code that holds a pointer to a context
- * must hold a reference count on it. The kgsl device
- * mutex must be held while the context reference count
- * is changed.
- */
-static inline void
-kgsl_context_get(struct kgsl_context *context)
-{
-	kref_get(&context->refcount);
-}
-
 void kgsl_context_destroy(struct kref *kref);
 
 /**
- * kgsl_context_put - Release context reference count
- * @context
+ * kgsl_context_put() - Release context reference count
+ * @context: Pointer to the KGSL context to be released
  *
+ * Reduce the reference count on a KGSL context and destroy it if it is no
+ * longer needed
  */
 static inline void
 kgsl_context_put(struct kgsl_context *context)
 {
-	kref_put(&context->refcount, kgsl_context_destroy);
+	if (context)
+		kref_put(&context->refcount, kgsl_context_destroy);
+}
+/**
+ * kgsl_context_get() - get a pointer to a KGSL context
+ * @device: Pointer to the KGSL device that owns the context
+ * @id: Context ID
+ *
+ * Find the context associated with the given ID number, increase the reference
+ * count on it and return it.  The caller must make sure that this call is
+ * paired with a kgsl_context_put.  This function is for internal use because it
+ * doesn't validate the ownership of the context with the calling process - use
+ * kgsl_context_get_owner for that
+ */
+static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device,
+		uint32_t id)
+{
+	struct kgsl_context *context = NULL;
+
+	read_lock(&device->context_lock);
+
+	context = idr_find(&device->context_idr, id);
+
+	if (context)
+		kref_get(&context->refcount);
+
+	read_unlock(&device->context_lock);
+
+	return context;
+}
+
+/**
+ * kgsl_context_get_owner() - get a pointer to a KGSL context in a specific
+ * process
+ * @dev_priv: Pointer to the process struct
+ * @id: Context ID to return
+ *
+ * Find the context associated with the given ID number, increase the reference
+ * count on it and return it.  The caller must make sure that this call is
+ * paired with a kgsl_context_put. This function validates that the context id
+ * given is owned by the dev_priv instancet that is passed in.  See
+ * kgsl_context_get for the internal version that doesn't do the check
+ */
+static inline struct kgsl_context *kgsl_context_get_owner(
+		struct kgsl_device_private *dev_priv, uint32_t id)
+{
+	struct kgsl_context *context;
+
+	context = kgsl_context_get(dev_priv->device, id);
+
+	/* Verify that the context belongs to the dev_priv instance */
+	if (context && context->dev_priv != dev_priv) {
+		kgsl_context_put(context);
+		return NULL;
+	}
+
+	return context;
 }
 
 #endif  /* __KGSL_DEVICE_H */
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index a1fc5a2..0b75175 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -60,7 +60,7 @@
 		return -EINVAL;
 
 	if (id != KGSL_MEMSTORE_GLOBAL) {
-		context = idr_find(&device->context_idr, id);
+		context = kgsl_context_get(device, id);
 		if (context == NULL)
 			return -EINVAL;
 	}
@@ -76,12 +76,15 @@
 	if (timestamp_cmp(cur_ts, ts) >= 0) {
 		trace_kgsl_fire_event(id, ts, 0);
 		cb(device, priv, id, ts);
+		kgsl_context_put(context);
 		return 0;
 	}
 
 	event = kzalloc(sizeof(*event), GFP_KERNEL);
-	if (event == NULL)
+	if (event == NULL) {
+		kgsl_context_put(context);
 		return -ENOMEM;
+	}
 
 	/*
 	 * Increase the active count on the device to avoid going into power
@@ -89,6 +92,7 @@
 	 */
 	ret = kgsl_active_count_get_light(device);
 	if (ret < 0) {
+		kgsl_context_put(context);
 		kfree(event);
 		return ret;
 	}
@@ -102,10 +106,6 @@
 
 	trace_kgsl_register_event(id, ts);
 
-	/* inc refcount to avoid race conditions in cleanup */
-	if (context)
-		kgsl_context_get(context);
-
 	/* Add the event to either the owning context or the global list */
 
 	if (context) {
@@ -147,7 +147,7 @@
 	 * Increment the refcount to avoid freeing the context while
 	 * cancelling its events
 	 */
-	kgsl_context_get(context);
+	kref_get(&context->refcount);
 
 	/* Remove ourselves from the master pending list */
 	list_del_init(&context->events_list);
@@ -324,7 +324,7 @@
 		 * Increment the refcount to make sure that the list_del_init
 		 * is called with a valid context's list
 		 */
-		kgsl_context_get(context);
+		kref_get(&context->refcount);
 		/*
 		 * If kgsl_timestamp_expired_context returns 0 then it no longer
 		 * has any pending events and can be removed from the list
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 9113605..ace6121 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -325,7 +325,6 @@
 	unsigned int no_page_fault_log = 0;
 	unsigned int curr_context_id = 0;
 	unsigned int curr_global_ts = 0;
-	static struct adreno_context *curr_context;
 	static struct kgsl_context *context;
 
 	ret = get_iommu_unit(dev, &mmu, &iommu_unit);
@@ -396,9 +395,11 @@
 
 	kgsl_sharedmem_readl(&device->memstore, &curr_context_id,
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
-	context = idr_find(&device->context_idr, curr_context_id);
+
+	context = kgsl_context_get(device, curr_context_id);
+
 	if (context != NULL) {
-			curr_context = context->devctxt;
+		struct adreno_context *drawctxt = context->devctxt;
 
 		kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -408,8 +409,13 @@
 		 * Store pagefault's timestamp in adreno context,
 		 * this information will be used in GFT
 		 */
-		curr_context->pagefault = 1;
-		curr_context->pagefault_ts = curr_global_ts;
+
+		if (drawctxt != NULL) {
+			drawctxt->pagefault = 1;
+			drawctxt->pagefault_ts = curr_global_ts;
+		}
+
+		kgsl_context_put(context);
 	}
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
@@ -1534,6 +1540,7 @@
 				KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit,
 						iommu_unit->dev[j].ctx_id,
 						V2PUR, v2pxx);
+				mb();
 				vaddr += PAGE_SIZE;
 				for (l = 0; l < iommu_unit->dev_count; l++) {
 					tlblkcr = KGSL_IOMMU_GET_CTX_REG(iommu,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 91d462b..5e6d24b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1389,13 +1389,14 @@
 			(unsigned int *) &context_id,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 				current_context));
-		context = idr_find(&device->context_idr, context_id);
+		context = kgsl_context_get(device, context_id);
 		if (context)
 			ts_processed = kgsl_readtimestamp(device, context,
 				KGSL_TIMESTAMP_RETIRED);
 		KGSL_PWR_INFO(device, "Wake from %s state. CTXT: %d RTRD TS: %08X\n",
 			kgsl_pwrstate_to_str(state),
 			context ? context->id : -1, ts_processed);
+		kgsl_context_put(context);
 		/* fall through */
 	case KGSL_STATE_NAP:
 		/* Turn on the core clocks */
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index d3edbba..35f24d9 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -145,7 +145,9 @@
 	/* Figure out how many active contexts there are - these will
 	 * be appended on the end of the structure */
 
+	read_lock(&device->context_lock);
 	idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
+	read_unlock(&device->context_lock);
 
 	/* Increment ctxcount for the global memstore */
 	ctxtcount++;
@@ -202,7 +204,10 @@
 	/* append information for the global context */
 	snapshot_context_info(KGSL_MEMSTORE_GLOBAL, NULL, device);
 	/* append information for each context */
+
+	read_lock(&device->context_lock);
 	idr_for_each(&device->context_idr, snapshot_context_info, NULL);
+	read_unlock(&device->context_lock);
 
 	/* Return the size of the data segment */
 	return size;
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 2f67405..1853996c 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -121,16 +121,17 @@
 	if (len != sizeof(priv))
 		return -EINVAL;
 
-	context = kgsl_find_context(owner, context_id);
-	if (context == NULL)
-		return -EINVAL;
-
 	event = kzalloc(sizeof(*event), GFP_KERNEL);
 	if (event == NULL)
 		return -ENOMEM;
+
+	context = kgsl_context_get_owner(owner, context_id);
+
+	if (context == NULL)
+		goto fail_pt;
+
 	event->context = context;
 	event->timestamp = timestamp;
-	kgsl_context_get(context);
 
 	pt = kgsl_sync_pt_create(context->timeline, timestamp);
 	if (pt == NULL) {
@@ -161,6 +162,10 @@
 		goto fail_copy_fd;
 	}
 
+	/*
+	 * Hold the context ref-count for the event - it will get released in
+	 * the callback
+	 */
 	ret = kgsl_add_event(device, context_id, timestamp,
 			kgsl_fence_event_cb, event, owner);
 	if (ret)
@@ -185,12 +190,16 @@
 static unsigned int kgsl_sync_get_timestamp(
 	struct kgsl_sync_timeline *ktimeline, enum kgsl_timestamp_type type)
 {
-	struct kgsl_context *context = idr_find(&ktimeline->device->context_idr,
-						ktimeline->context_id);
-	if (context == NULL)
-		return 0;
+	unsigned int ret = 0;
 
-	return kgsl_readtimestamp(ktimeline->device, context, type);
+	struct kgsl_context *context = kgsl_context_get(ktimeline->device,
+			ktimeline->context_id);
+
+	if (context)
+		ret = kgsl_readtimestamp(ktimeline->device, context, type);
+
+	kgsl_context_put(context);
+	return ret;
 }
 
 static void kgsl_sync_timeline_value_str(struct sync_timeline *sync_timeline,
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 1464dab..a052bd3 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -654,4 +654,42 @@
           If you say yes here you get support for STMicroelectronics's
           acceleration sensors LIS3DH.
 
+config BMP18X
+       tristate "BMP18X digital pressure sensor"
+       depends on (I2C ) && SYSFS
+       help
+         If you say yes here you get support for Bosch Sensortec
+	 digital pressure sensors BMP085, BMP180.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bmp18x-core.
+
+config BMP18X_I2C
+       tristate "support I2C bus connection"
+       depends on BMP18X && I2C
+       help
+         Say Y here if you want to support Bosch Sensortec digital pressure
+         sensor hooked to an I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bmp18x-i2c.
+
+config SENSORS_MMA8X5X
+	tristate "MMA8451/MMA8452/MMA8453/MMA8652/MMA8653 device driver"
+	depends on I2C && SYSFS
+	select INPUT_POLLDEV
+	default n
+	help
+	  If you say yes here you get support for the Freescale MMA8451/
+	  MMA8452/MMA8453/MMA8652/MMA8653  sensors.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mma8x5x.
+
+config SENSORS_MMA_POSITION
+	int "MMA8x5x Accelerate Sensor Position Setting"
+	depends on SENSORS_MMA8X5X
+	default "0"
+	help
+	  this provide the sensor position setting , value is between 0~7
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 96c9288..4f29e05 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -61,3 +61,6 @@
 obj-$(CONFIG_INPUT_PMIC8058_VIBRA_MEMLESS) += pmic8058-vib-memless.o
 obj-$(CONFIG_BOSCH_BMA150)              += bma150.o
 obj-$(CONFIG_STM_LIS3DH)		+= lis3dh_acc.o
+obj-$(CONFIG_BMP18X)			+= bmp18x-core.o
+obj-$(CONFIG_BMP18X_I2C)		+= bmp18x-i2c.o
+obj-$(CONFIG_SENSORS_MMA8X5X)	  	+= mma8x5x.o
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
new file mode 100644
index 0000000..bac9059
--- /dev/null
+++ b/drivers/input/misc/bmp18x-core.c
@@ -0,0 +1,705 @@
+/*  Copyright (c) 2011  Bosch Sensortec GmbH
+    Copyright (c) 2011  Unixphere
+
+    Based on:
+    BMP085 driver, bmp085.c
+    Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
+
+    This driver supports the bmp18x digital barometric pressure
+    and temperature sensors from Bosch Sensortec.
+
+    A pressure measurement is issued by reading from pressure0_input.
+    The return value ranges from 30000 to 110000 pascal with a resulution
+    of 1 pascal (0.01 millibar) which enables measurements from 9000m above
+    to 500m below sea level.
+
+    The temperature can be read from temp0_input. Values range from
+    -400 to 850 representing the ambient temperature in degree celsius
+    multiplied by 10.The resolution is 0.1 celsius.
+
+    Because ambient pressure is temperature dependent, a temperature
+    measurement will be executed automatically even if the user is reading
+    from pressure0_input. This happens if the last temperature measurement
+    has been executed more then one second ago.
+
+    To decrease RMS noise from pressure measurements, the bmp18x can
+    autonomously calculate the average of up to eight samples. This is
+    set up by writing to the oversampling sysfs file. Accepted values
+    are 0, 1, 2 and 3. 2^x when x is the value written to this file
+    specifies the number of samples used to calculate the ambient pressure.
+    RMS noise is specified with six pascal (without averaging) and decreases
+    down to 3 pascal when using an oversampling setting of 3.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "bmp18x.h"
+
+#define BMP18X_CHIP_ID			0x55
+
+#define BMP18X_CALIBRATION_DATA_START	0xAA
+#define BMP18X_CALIBRATION_DATA_LENGTH	11	/* 16 bit values */
+#define BMP18X_CHIP_ID_REG		0xD0
+#define BMP18X_CTRL_REG			0xF4
+#define BMP18X_TEMP_MEASUREMENT		0x2E
+#define BMP18X_PRESSURE_MEASUREMENT	0x34
+#define BMP18X_CONVERSION_REGISTER_MSB	0xF6
+#define BMP18X_CONVERSION_REGISTER_LSB	0xF7
+#define BMP18X_CONVERSION_REGISTER_XLSB	0xF8
+#define BMP18X_TEMP_CONVERSION_TIME	5
+
+#define ABS_MIN_PRESSURE	30000
+#define ABS_MAX_PRESSURE	120000
+#define BMP_DELAY_DEFAULT   200
+
+struct bmp18x_calibration_data {
+	s16 AC1, AC2, AC3;
+	u16 AC4, AC5, AC6;
+	s16 B1, B2;
+	s16 MB, MC, MD;
+};
+
+/* Each client has this additional data */
+struct bmp18x_data {
+	struct	bmp18x_data_bus data_bus;
+	struct	device *dev;
+	struct	mutex lock;
+	struct	bmp18x_calibration_data calibration;
+	u8	oversampling_setting;
+	u8	sw_oversampling_setting;
+	u32	raw_temperature;
+	u32	raw_pressure;
+	u32	temp_measurement_period;
+	u32	last_temp_measurement;
+	s32	b6; /* calculated temperature correction coefficient */
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct early_suspend early_suspend;
+#endif
+	struct input_dev	*input;
+	struct delayed_work work;
+	u32					delay;
+	u32					enable;
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bmp18x_early_suspend(struct early_suspend *h);
+static void bmp18x_late_resume(struct early_suspend *h);
+#endif
+
+static s32 bmp18x_read_calibration_data(struct bmp18x_data *data)
+{
+	u16 tmp[BMP18X_CALIBRATION_DATA_LENGTH];
+	struct bmp18x_calibration_data *cali = &(data->calibration);
+	s32 status = data->data_bus.bops->read_block(data->data_bus.client,
+				BMP18X_CALIBRATION_DATA_START,
+				BMP18X_CALIBRATION_DATA_LENGTH*sizeof(u16),
+				(u8 *)tmp);
+	if (status < 0)
+		return status;
+
+	if (status != BMP18X_CALIBRATION_DATA_LENGTH*sizeof(u16))
+		return -EIO;
+
+	cali->AC1 =  be16_to_cpu(tmp[0]);
+	cali->AC2 =  be16_to_cpu(tmp[1]);
+	cali->AC3 =  be16_to_cpu(tmp[2]);
+	cali->AC4 =  be16_to_cpu(tmp[3]);
+	cali->AC5 =  be16_to_cpu(tmp[4]);
+	cali->AC6 = be16_to_cpu(tmp[5]);
+	cali->B1 = be16_to_cpu(tmp[6]);
+	cali->B2 = be16_to_cpu(tmp[7]);
+	cali->MB = be16_to_cpu(tmp[8]);
+	cali->MC = be16_to_cpu(tmp[9]);
+	cali->MD = be16_to_cpu(tmp[10]);
+	return 0;
+}
+
+
+static s32 bmp18x_update_raw_temperature(struct bmp18x_data *data)
+{
+	u16 tmp;
+	s32 status;
+
+	mutex_lock(&data->lock);
+	status = data->data_bus.bops->write_byte(data->data_bus.client,
+				BMP18X_CTRL_REG, BMP18X_TEMP_MEASUREMENT);
+	if (status != 0) {
+		dev_err(data->dev,
+			"Error while requesting temperature measurement.\n");
+		goto exit;
+	}
+	msleep(BMP18X_TEMP_CONVERSION_TIME);
+
+	status = data->data_bus.bops->read_block(data->data_bus.client,
+		BMP18X_CONVERSION_REGISTER_MSB, sizeof(tmp), (u8 *)&tmp);
+	if (status < 0)
+		goto exit;
+	if (status != sizeof(tmp)) {
+		dev_err(data->dev,
+			"Error while reading temperature measurement result\n");
+		status = -EIO;
+		goto exit;
+	}
+	data->raw_temperature = be16_to_cpu(tmp);
+	data->last_temp_measurement = jiffies;
+	status = 0;	/* everything ok, return 0 */
+
+exit:
+	mutex_unlock(&data->lock);
+	return status;
+}
+
+static s32 bmp18x_update_raw_pressure(struct bmp18x_data *data)
+{
+	u32 tmp = 0;
+	s32 status;
+
+	mutex_lock(&data->lock);
+	status = data->data_bus.bops->write_byte(data->data_bus.client,
+		BMP18X_CTRL_REG, BMP18X_PRESSURE_MEASUREMENT +
+		(data->oversampling_setting<<6));
+	if (status != 0) {
+		dev_err(data->dev,
+			"Error while requesting pressure measurement.\n");
+		goto exit;
+	}
+
+	/* wait for the end of conversion */
+	msleep(2+(3 << data->oversampling_setting));
+
+	/* copy data into a u32 (4 bytes), but skip the first byte. */
+	status = data->data_bus.bops->read_block(data->data_bus.client,
+			BMP18X_CONVERSION_REGISTER_MSB, 3, ((u8 *)&tmp)+1);
+	if (status < 0)
+		goto exit;
+	if (status != 3) {
+		dev_err(data->dev,
+			"Error while reading pressure measurement results\n");
+		status = -EIO;
+		goto exit;
+	}
+	data->raw_pressure = be32_to_cpu((tmp));
+	data->raw_pressure >>= (8-data->oversampling_setting);
+	status = 0;	/* everything ok, return 0 */
+
+exit:
+	mutex_unlock(&data->lock);
+	return status;
+}
+
+
+/*
+ * This function starts the temperature measurement and returns the value
+ * in tenth of a degree celsius.
+ */
+static s32 bmp18x_get_temperature(struct bmp18x_data *data, int *temperature)
+{
+	struct bmp18x_calibration_data *cali = &data->calibration;
+	long x1, x2;
+	int status;
+
+	status = bmp18x_update_raw_temperature(data);
+	if (status != 0)
+		goto exit;
+
+	x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
+	x2 = (cali->MC << 11) / (x1 + cali->MD);
+	data->b6 = x1 + x2 - 4000;
+	/* if NULL just update b6. Used for pressure only measurements */
+	if (temperature != NULL)
+		*temperature = (x1+x2+8) >> 4;
+
+exit:
+	return status;
+}
+
+/*
+ * This function starts the pressure measurement and returns the value
+ * in millibar. Since the pressure depends on the ambient temperature,
+ * a temperature measurement is executed according to the given temperature
+ * measurememt period (default is 1 sec boundary). This period could vary
+ * and needs to be adjusted accoring to the sensor environment, i.e. if big
+ * temperature variations then the temperature needs to be read out often.
+ */
+static s32 bmp18x_get_pressure(struct bmp18x_data *data, int *pressure)
+{
+	struct bmp18x_calibration_data *cali = &data->calibration;
+	s32 x1, x2, x3, b3;
+	u32 b4, b7;
+	s32 p;
+	int status;
+	int i_loop, i;
+	u32 p_tmp;
+
+	/* update the ambient temperature according to the given meas. period */
+	if (data->last_temp_measurement +
+			data->temp_measurement_period < jiffies) {
+		status = bmp18x_get_temperature(data, NULL);
+		if (status != 0)
+			goto exit;
+	}
+
+	if ((data->oversampling_setting == 3)
+		&& (data->sw_oversampling_setting == 1)) {
+		i_loop = 3;
+	} else {
+		i_loop = 1;
+	}
+
+	p_tmp = 0;
+	for (i = 0; i < i_loop; i++) {
+		status = bmp18x_update_raw_pressure(data);
+		if (status != 0)
+			goto exit;
+		p_tmp += data->raw_pressure;
+	}
+
+	data->raw_pressure = (p_tmp + (i_loop >> 1)) / i_loop;
+
+	x1 = (data->b6 * data->b6) >> 12;
+	x1 *= cali->B2;
+	x1 >>= 11;
+
+	x2 = cali->AC2 * data->b6;
+	x2 >>= 11;
+
+	x3 = x1 + x2;
+
+	b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2);
+	b3 >>= 2;
+
+	x1 = (cali->AC3 * data->b6) >> 13;
+	x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
+	x3 = (x1 + x2 + 2) >> 2;
+	b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15;
+
+	b7 = ((u32)data->raw_pressure - b3) *
+					(50000 >> data->oversampling_setting);
+	p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
+
+	x1 = p >> 8;
+	x1 *= x1;
+	x1 = (x1 * 3038) >> 16;
+	x2 = (-7357 * p) >> 16;
+	p += (x1 + x2 + 3791) >> 4;
+
+	*pressure = p;
+
+exit:
+	return status;
+}
+
+/*
+ * This function sets the chip-internal oversampling. Valid values are 0..3.
+ * The chip will use 2^oversampling samples for internal averaging.
+ * This influences the measurement time and the accuracy; larger values
+ * increase both. The datasheet gives on overview on how measurement time,
+ * accuracy and noise correlate.
+ */
+static void bmp18x_set_oversampling(struct bmp18x_data *data,
+						unsigned char oversampling)
+{
+	if (oversampling > 3)
+		oversampling = 3;
+	data->oversampling_setting = oversampling;
+}
+
+/*
+ * Returns the currently selected oversampling. Range: 0..3
+ */
+static unsigned char bmp18x_get_oversampling(struct bmp18x_data *data)
+{
+	return data->oversampling_setting;
+}
+
+/* sysfs callbacks */
+static ssize_t set_oversampling(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	unsigned long oversampling;
+	int success = kstrtoul(buf, 10, &oversampling);
+	if (success == 0) {
+		mutex_lock(&data->lock);
+		bmp18x_set_oversampling(data, oversampling);
+		if (oversampling != 3)
+			data->sw_oversampling_setting = 0;
+		mutex_unlock(&data->lock);
+		return count;
+	}
+	return success;
+}
+
+static ssize_t show_oversampling(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE,
+		"%u\n", bmp18x_get_oversampling(data));
+}
+static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
+					show_oversampling, set_oversampling);
+
+static ssize_t set_sw_oversampling(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	unsigned long sw_oversampling;
+	int success = kstrtoul(buf, 10, &sw_oversampling);
+	if (success == 0) {
+		mutex_lock(&data->lock);
+		data->sw_oversampling_setting = sw_oversampling ? 1 : 0;
+		mutex_unlock(&data->lock);
+	}
+	return success;
+}
+
+static ssize_t show_sw_oversampling(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE,
+		"%u\n", data->sw_oversampling_setting);
+}
+static DEVICE_ATTR(sw_oversampling, S_IWUSR | S_IRUGO,
+				show_sw_oversampling, set_sw_oversampling);
+
+static ssize_t show_delay(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", data->delay);
+}
+
+static ssize_t set_delay(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	unsigned long delay;
+	int success = kstrtoul(buf, 10, &delay);
+	if (success == 0) {
+		mutex_lock(&data->lock);
+		data->delay = delay;
+		mutex_unlock(&data->lock);
+	}
+	return success;
+}
+static DEVICE_ATTR(delay, S_IWUSR | S_IRUGO,
+				show_delay, set_delay);
+
+static ssize_t show_enable(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", data->enable);
+}
+
+static ssize_t set_enable(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	unsigned long enable;
+	int success = kstrtoul(buf, 10, &enable);
+	if (success == 0) {
+		mutex_lock(&data->lock);
+		data->enable = enable ? 1 : 0;
+
+		if (data->enable) {
+			bmp18x_enable(dev);
+			schedule_delayed_work(&data->work,
+						msecs_to_jiffies(data->delay));
+		} else {
+			cancel_delayed_work_sync(&data->work);
+			bmp18x_disable(dev);
+		}
+		mutex_unlock(&data->lock);
+
+	}
+	return success;
+}
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+				show_enable, set_enable);
+
+static ssize_t show_temperature(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int temperature;
+	int status;
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	status = bmp18x_get_temperature(data, &temperature);
+	if (status != 0)
+		return status;
+	else
+		return snprintf(buf, PAGE_SIZE,
+			"%d\n", temperature);
+}
+static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
+
+
+static ssize_t show_pressure(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	int pressure;
+	int status;
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	status = bmp18x_get_pressure(data, &pressure);
+	if (status != 0)
+		return status;
+	else
+		return snprintf(buf, PAGE_SIZE, "%d\n", pressure);
+}
+static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
+
+
+static struct attribute *bmp18x_attributes[] = {
+	&dev_attr_temp0_input.attr,
+	&dev_attr_pressure0_input.attr,
+	&dev_attr_oversampling.attr,
+	&dev_attr_sw_oversampling.attr,
+	&dev_attr_delay.attr,
+	&dev_attr_enable.attr,
+	NULL
+};
+
+static const struct attribute_group bmp18x_attr_group = {
+	.attrs = bmp18x_attributes,
+};
+
+static void bmp18x_work_func(struct work_struct *work)
+{
+	struct bmp18x_data *client_data =
+		container_of((struct delayed_work *)work,
+		struct bmp18x_data, work);
+	unsigned long delay = msecs_to_jiffies(client_data->delay);
+	unsigned long j1 = jiffies;
+	int pressure;
+	int status;
+
+	status = bmp18x_get_pressure(client_data, &pressure);
+
+	if (status == 0) {
+		input_report_abs(client_data->input, ABS_PRESSURE, pressure);
+		input_sync(client_data->input);
+	}
+
+	schedule_delayed_work(&client_data->work, delay-(jiffies-j1));
+}
+
+static int bmp18x_input_init(struct bmp18x_data *data)
+{
+	struct input_dev *dev;
+	int err;
+
+	dev = input_allocate_device();
+	if (!dev)
+		return -ENOMEM;
+	dev->name = BMP18X_NAME;
+	dev->id.bustype = BUS_I2C;
+
+	input_set_capability(dev, EV_ABS, ABS_MISC);
+	input_set_abs_params(dev, ABS_PRESSURE,
+		ABS_MIN_PRESSURE, ABS_MAX_PRESSURE, 0, 0);
+	input_set_drvdata(dev, data);
+
+	err = input_register_device(dev);
+	if (err < 0) {
+		input_free_device(dev);
+		return err;
+	}
+	data->input = dev;
+
+	return 0;
+}
+
+static void bmp18x_input_delete(struct bmp18x_data *data)
+{
+	struct input_dev *dev = data->input;
+
+	input_unregister_device(dev);
+	input_free_device(dev);
+}
+
+static int bmp18x_init_client(struct bmp18x_data *data,
+			      struct bmp18x_platform_data *pdata)
+{
+	int status = bmp18x_read_calibration_data(data);
+	if (status != 0)
+		goto exit;
+	data->last_temp_measurement = 0;
+	data->temp_measurement_period =
+		pdata ? (pdata->temp_measurement_period/1000)*HZ : 1*HZ;
+	data->oversampling_setting = pdata ? pdata->default_oversampling : 3;
+	if (data->oversampling_setting == 3)
+		data->sw_oversampling_setting
+			= pdata ? pdata->default_sw_oversampling : 0;
+	mutex_init(&data->lock);
+exit:
+	return status;
+}
+
+__devinit int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus)
+{
+	struct bmp18x_data *data;
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+	u8 chip_id = pdata && pdata->chip_id ? pdata->chip_id : BMP18X_CHIP_ID;
+	int err = 0;
+
+	if (pdata && pdata->init_hw) {
+		err = pdata->init_hw();
+		if (err) {
+			printk(KERN_ERR "%s: init_hw failed!\n",
+				BMP18X_NAME);
+			goto exit;
+		}
+	}
+
+	if (data_bus->bops->read_byte(data_bus->client,
+			BMP18X_CHIP_ID_REG) != chip_id) {
+		printk(KERN_ERR "%s: chip_id failed!\n", BMP18X_NAME);
+		err = -ENODEV;
+		goto exit;
+	}
+
+	data = kzalloc(sizeof(struct bmp18x_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	dev_set_drvdata(dev, data);
+	data->data_bus = *data_bus;
+	data->dev = dev;
+
+	/* Initialize the BMP18X chip */
+	err = bmp18x_init_client(data, pdata);
+	if (err != 0)
+		goto exit_free;
+
+	/* Initialize the BMP18X input device */
+	err = bmp18x_input_init(data);
+	if (err != 0)
+		goto exit_free;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&data->input->dev.kobj, &bmp18x_attr_group);
+	if (err)
+		goto error_sysfs;
+	/* workqueue init */
+	INIT_DELAYED_WORK(&data->work, bmp18x_work_func);
+	data->delay  = BMP_DELAY_DEFAULT;
+	data->enable = 0;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	data->early_suspend.suspend = bmp18x_early_suspend;
+	data->early_suspend.resume = bmp18x_late_resume;
+	register_early_suspend(&data->early_suspend);
+#endif
+
+	dev_info(dev, "Succesfully initialized bmp18x!\n");
+	return 0;
+
+error_sysfs:
+	bmp18x_input_delete(data);
+exit_free:
+	kfree(data);
+exit:
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw();
+	return err;
+}
+EXPORT_SYMBOL(bmp18x_probe);
+
+int bmp18x_remove(struct device *dev)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	unregister_early_suspend(&data->early_suspend);
+#endif
+	sysfs_remove_group(&data->input->dev.kobj, &bmp18x_attr_group);
+	kfree(data);
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_remove);
+
+#ifdef CONFIG_PM
+int bmp18x_disable(struct device *dev)
+{
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw();
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_disable);
+
+int bmp18x_enable(struct device *dev)
+{
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+
+	if (pdata && pdata->init_hw)
+		return pdata->init_hw();
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_enable);
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bmp18x_early_suspend(struct early_suspend *h)
+{
+	struct bmp18x_data *data =
+		container_of(h, struct bmp18x_data, early_suspend);
+	if (data->enable) {
+		cancel_delayed_work_sync(&data->work);
+		(void) bmp18x_disable(data->dev);
+	}
+}
+
+static void bmp18x_late_resume(struct early_suspend *h)
+{
+	struct bmp18x_data *data =
+		container_of(h, struct bmp18x_data, early_suspend);
+
+	if (data->enable) {
+		(void) bmp18x_enable(data->dev);
+		schedule_delayed_work(&data->work,
+					msecs_to_jiffies(data->delay));
+	}
+
+}
+#endif
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
new file mode 100644
index 0000000..6c01ad3
--- /dev/null
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -0,0 +1,122 @@
+/*  Copyright (c) 2011  Bosch Sensortec GmbH
+    Copyright (c) 2011  Unixphere
+
+    Based on:
+    BMP085 driver, bmp085.c
+    Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include "bmp18x.h"
+
+static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
+{
+	return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
+}
+
+static int bmp18x_i2c_read_byte(void *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int bmp18x_i2c_write_byte(void *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static const struct bmp18x_bus_ops bmp18x_i2c_bus_ops = {
+	.read_block	= bmp18x_i2c_read_block,
+	.read_byte	= bmp18x_i2c_read_byte,
+	.write_byte	= bmp18x_i2c_write_byte
+};
+
+static int __devinit bmp18x_i2c_probe(struct i2c_client *client,
+				      const struct i2c_device_id *id)
+{
+	struct bmp18x_data_bus data_bus = {
+		.bops = &bmp18x_i2c_bus_ops,
+		.client = client
+	};
+
+	return bmp18x_probe(&client->dev, &data_bus);
+}
+
+static void bmp18x_i2c_shutdown(struct i2c_client *client)
+{
+	bmp18x_disable(&client->dev);
+}
+
+static int bmp18x_i2c_remove(struct i2c_client *client)
+{
+	return bmp18x_remove(&client->dev);
+}
+
+#ifdef CONFIG_PM
+static int bmp18x_i2c_suspend(struct device *dev)
+{
+	return bmp18x_disable(dev);
+}
+
+static int bmp18x_i2c_resume(struct device *dev)
+{
+	return bmp18x_enable(dev);
+}
+
+static const struct dev_pm_ops bmp18x_i2c_pm_ops = {
+	.suspend	= bmp18x_i2c_suspend,
+	.resume		= bmp18x_i2c_resume
+};
+#endif
+
+static const struct i2c_device_id bmp18x_id[] = {
+	{ BMP18X_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bmp18x_id);
+
+static struct i2c_driver bmp18x_i2c_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMP18X_NAME,
+#ifdef CONFIG_PM
+		.pm	= &bmp18x_i2c_pm_ops,
+#endif
+	},
+	.id_table	= bmp18x_id,
+	.probe		= bmp18x_i2c_probe,
+	.shutdown	= bmp18x_i2c_shutdown,
+	.remove		= __devexit_p(bmp18x_i2c_remove)
+};
+
+static int __init bmp18x_i2c_init(void)
+{
+	return i2c_add_driver(&bmp18x_i2c_driver);
+}
+
+static void __exit bmp18x_i2c_exit(void)
+{
+	i2c_del_driver(&bmp18x_i2c_driver);
+}
+
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X I2C bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp18x_i2c_init);
+module_exit(bmp18x_i2c_exit);
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
new file mode 100644
index 0000000..f9d55ec
--- /dev/null
+++ b/drivers/input/misc/bmp18x.h
@@ -0,0 +1,64 @@
+/*  Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
+    Copyright (c) 2011  Bosch Sensortec GmbH
+    Copyright (c) 2011  Unixphere AB
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef _BMP18X_H
+#define _BMP18X_H
+
+#define BMP18X_NAME "bmp18x"
+
+/**
+ * struct bmp18x_platform_data - represents platform data for the bmp18x driver
+ * @chip_id: Configurable chip id for non-default chip revisions
+ * @default_oversampling: Default oversampling value to be used at startup,
+ * value range is 0-3 with rising sensitivity.
+ * @default_sw_oversampling: Default software oversampling value to be used
+ * at startup,value range is 0(Disabled) or 1(Enabled). Only take effect
+ * when default_oversampling is 3.
+ * @temp_measurement_period: Temperature measurement period (milliseconds), set
+ * to zero if unsure.
+ * @init_hw: Callback for hw specific startup
+ * @deinit_hw: Callback for hw specific shutdown
+ */
+struct bmp18x_platform_data {
+	u8	chip_id;
+	u8	default_oversampling;
+	u8	default_sw_oversampling;
+	u32	temp_measurement_period;
+	int	(*init_hw)(void);
+	void	(*deinit_hw)(void);
+};
+
+struct bmp18x_bus_ops {
+	int	(*read_block)(void *client, u8 reg, int len, char *buf);
+	int	(*read_byte)(void *client, u8 reg);
+	int	(*write_byte)(void *client, u8 reg, u8 value);
+};
+
+struct bmp18x_data_bus {
+	const struct bmp18x_bus_ops	*bops;
+	void	*client;
+};
+
+int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
+int bmp18x_remove(struct device *dev);
+#ifdef CONFIG_PM
+int bmp18x_enable(struct device *dev);
+int bmp18x_disable(struct device *dev);
+#endif
+
+#endif
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
new file mode 100644
index 0000000..8a0d4ab
--- /dev/null
+++ b/drivers/input/misc/mma8x5x.c
@@ -0,0 +1,645 @@
+/*
+ *  mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
+ *  Detection Sensor MMA8451/MMA8452/MMA8453
+ *
+ *  Copyright (C) 2010-2011 Freescale Semiconductor, Inc. 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 as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
+
+#define MMA8X5X_I2C_ADDR	0x1D
+#define MMA8451_ID			0x1A
+#define MMA8452_ID			0x2A
+#define MMA8453_ID			0x3A
+#define MMA8652_ID			0x4A
+#define MMA8653_ID			0x5A
+
+
+#define POLL_INTERVAL_MIN	1
+#define POLL_INTERVAL_MAX	500
+#define POLL_INTERVAL		100 /* msecs */
+
+/* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
+#define POLL_STOP_TIME		200
+#define INPUT_FUZZ			32
+#define INPUT_FLAT			32
+#define MODE_CHANGE_DELAY_MS	100
+
+#define MMA8X5X_STATUS_ZYXDR	0x08
+#define MMA8X5X_BUF_SIZE	7
+
+struct sensor_regulator {
+	struct regulator *vreg;
+	const char *name;
+	u32	min_uV;
+	u32	max_uV;
+};
+
+static struct sensor_regulator mma_vreg[] = {
+	{NULL, "vdd", 2850000, 2850000},
+	{NULL, "vio", 1800000, 1800000},
+};
+
+/* register enum for mma8x5x registers */
+enum {
+	MMA8X5X_STATUS = 0x00,
+	MMA8X5X_OUT_X_MSB,
+	MMA8X5X_OUT_X_LSB,
+	MMA8X5X_OUT_Y_MSB,
+	MMA8X5X_OUT_Y_LSB,
+	MMA8X5X_OUT_Z_MSB,
+	MMA8X5X_OUT_Z_LSB,
+
+	MMA8X5X_F_SETUP = 0x09,
+	MMA8X5X_TRIG_CFG,
+	MMA8X5X_SYSMOD,
+	MMA8X5X_INT_SOURCE,
+	MMA8X5X_WHO_AM_I,
+	MMA8X5X_XYZ_DATA_CFG,
+	MMA8X5X_HP_FILTER_CUTOFF,
+
+	MMA8X5X_PL_STATUS,
+	MMA8X5X_PL_CFG,
+	MMA8X5X_PL_COUNT,
+	MMA8X5X_PL_BF_ZCOMP,
+	MMA8X5X_P_L_THS_REG,
+
+	MMA8X5X_FF_MT_CFG,
+	MMA8X5X_FF_MT_SRC,
+	MMA8X5X_FF_MT_THS,
+	MMA8X5X_FF_MT_COUNT,
+
+	MMA8X5X_TRANSIENT_CFG = 0x1D,
+	MMA8X5X_TRANSIENT_SRC,
+	MMA8X5X_TRANSIENT_THS,
+	MMA8X5X_TRANSIENT_COUNT,
+
+	MMA8X5X_PULSE_CFG,
+	MMA8X5X_PULSE_SRC,
+	MMA8X5X_PULSE_THSX,
+	MMA8X5X_PULSE_THSY,
+	MMA8X5X_PULSE_THSZ,
+	MMA8X5X_PULSE_TMLT,
+	MMA8X5X_PULSE_LTCY,
+	MMA8X5X_PULSE_WIND,
+
+	MMA8X5X_ASLP_COUNT,
+	MMA8X5X_CTRL_REG1,
+	MMA8X5X_CTRL_REG2,
+	MMA8X5X_CTRL_REG3,
+	MMA8X5X_CTRL_REG4,
+	MMA8X5X_CTRL_REG5,
+
+	MMA8X5X_OFF_X,
+	MMA8X5X_OFF_Y,
+	MMA8X5X_OFF_Z,
+
+	MMA8X5X_REG_END,
+};
+
+/* The sensitivity is represented in counts/g. In 2g mode the
+sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
+counts/g and in 8g mode the sensitivity is 256 counts/g.
+ */
+enum {
+	MODE_2G = 0,
+	MODE_4G,
+	MODE_8G,
+};
+
+enum {
+	MMA_STANDBY = 0,
+	MMA_ACTIVED,
+};
+struct mma8x5x_data_axis {
+	short x;
+	short y;
+	short z;
+};
+struct mma8x5x_data {
+	struct i2c_client *client;
+	struct input_polled_dev *poll_dev;
+	struct mutex data_lock;
+	int active;
+	int position;
+	u8 chip_id;
+	int mode;
+};
+/* Addresses scanned */
+static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
+
+static int mma8x5x_chip_id[] = {
+	MMA8451_ID,
+	MMA8452_ID,
+	MMA8453_ID,
+	MMA8652_ID,
+	MMA8653_ID,
+};
+static char *mma8x5x_names[] = {
+	"mma8451",
+	"mma8452",
+	"mma8453",
+	"mma8652",
+	"mma8653",
+};
+static int mma8x5x_position_setting[8][3][3] = {
+	{{ 0, -1,  0}, { 1,  0,	0}, {0, 0,	1} },
+	{{-1,  0,  0}, { 0, -1,	0}, {0, 0,	1} },
+	{{ 0,  1,  0}, {-1,  0,	0}, {0, 0,	1} },
+	{{ 1,  0,  0}, { 0,  1,	0}, {0, 0,	1} },
+	{{ 0, -1,  0}, {-1,  0,	0}, {0, 0,  -1} },
+	{{-1,  0,  0}, { 0,  1,	0}, {0, 0,  -1} },
+	{{ 0,  1,  0}, { 1,  0,	0}, {0, 0,  -1} },
+	{{ 1,  0,  0}, { 0, -1,	0}, {0, 0,  -1} },
+};
+
+static int mma8x5x_config_regulator(struct i2c_client *client, bool on)
+{
+	int rc = 0, i;
+	int num_vreg = sizeof(mma_vreg)/sizeof(struct sensor_regulator);
+
+	if (on) {
+		for (i = 0; i < num_vreg; i++) {
+			mma_vreg[i].vreg = regulator_get(&client->dev,
+					mma_vreg[i].name);
+			if (IS_ERR(mma_vreg[i].vreg)) {
+				rc = PTR_ERR(mma_vreg[i].vreg);
+				dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+						__func__, rc);
+				mma_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+			if (regulator_count_voltages(mma_vreg[i].vreg) > 0) {
+				rc = regulator_set_voltage(mma_vreg[i].vreg,
+					mma_vreg[i].min_uV, mma_vreg[i].max_uV);
+				if (rc) {
+					dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+							__func__, rc);
+					regulator_put(mma_vreg[i].vreg);
+					mma_vreg[i].vreg = NULL;
+					goto error_vdd;
+				}
+			}
+			rc = regulator_enable(mma_vreg[i].vreg);
+			if (rc) {
+				dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+						__func__, rc);
+				if (regulator_count_voltages(mma_vreg[i].vreg)
+						> 0) {
+					regulator_set_voltage(mma_vreg[i].vreg,
+							0, mma_vreg[i].max_uV);
+				}
+				regulator_put(mma_vreg[i].vreg);
+				mma_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+		}
+		return rc;
+	} else {
+		i = num_vreg;
+	}
+error_vdd:
+	while (--i >= 0) {
+		if (!IS_ERR_OR_NULL(mma_vreg[i].vreg)) {
+			if (regulator_count_voltages(
+				mma_vreg[i].vreg) > 0) {
+				regulator_set_voltage(mma_vreg[i].vreg, 0,
+						mma_vreg[i].max_uV);
+			}
+			regulator_disable(mma_vreg[i].vreg);
+			regulator_put(mma_vreg[i].vreg);
+			mma_vreg[i].vreg = NULL;
+		}
+	}
+	return rc;
+}
+
+static int mma8x5x_data_convert(struct mma8x5x_data *pdata,
+		struct mma8x5x_data_axis *axis_data)
+{
+	short rawdata[3], data[3];
+	int i, j;
+	int position = pdata->position ;
+	if (position < 0 || position > 7)
+		position = 0;
+	rawdata[0] = axis_data->x;
+	rawdata[1] = axis_data->y;
+	rawdata[2] = axis_data->z;
+	for (i = 0; i < 3 ; i++) {
+		data[i] = 0;
+		for (j = 0; j < 3; j++)
+			data[i] += rawdata[j] *
+				mma8x5x_position_setting[position][i][j];
+	}
+	axis_data->x = data[0];
+	axis_data->y = data[1];
+	axis_data->z = data[2];
+	return 0;
+}
+static int mma8x5x_check_id(int id)
+{
+	int i = 0;
+	for (i = 0; i < sizeof(mma8x5x_chip_id)/sizeof(mma8x5x_chip_id[0]);
+			i++)
+		if (id == mma8x5x_chip_id[i])
+			return 1;
+	return 0;
+}
+static char *mma8x5x_id2name(u8 id)
+{
+	return mma8x5x_names[(id >> 4)-1];
+}
+static int mma8x5x_device_init(struct i2c_client *client)
+{
+	int result;
+	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0);
+	if (result < 0)
+		goto out;
+
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
+					   pdata->mode);
+	if (result < 0)
+		goto out;
+	pdata->active = MMA_STANDBY;
+	msleep(MODE_CHANGE_DELAY_MS);
+	return 0;
+out:
+	dev_err(&client->dev, "error when init mma8x5x:(%d)", result);
+	return result;
+}
+static int mma8x5x_device_stop(struct i2c_client *client)
+{
+	u8 val;
+	val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+	i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & 0xfe);
+	return 0;
+}
+
+static int mma8x5x_read_data(struct i2c_client *client,
+		struct mma8x5x_data_axis *data)
+{
+	u8 tmp_data[MMA8X5X_BUF_SIZE];
+	int ret;
+
+	ret = i2c_smbus_read_i2c_block_data(client,
+					    MMA8X5X_OUT_X_MSB, 7, tmp_data);
+	if (ret < MMA8X5X_BUF_SIZE) {
+		dev_err(&client->dev, "i2c block read failed\n");
+		return -EIO;
+	}
+	data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+	data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+	data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+	return 0;
+}
+
+static void mma8x5x_report_data(struct mma8x5x_data *pdata)
+{
+	struct input_polled_dev *poll_dev = pdata->poll_dev;
+	struct mma8x5x_data_axis data;
+	mutex_lock(&pdata->data_lock);
+	if (pdata->active == MMA_STANDBY) {
+		poll_dev->poll_interval = POLL_STOP_TIME;
+		/* if standby ,set as 10s to slow the poll. */
+		goto out;
+	} else {
+		if (poll_dev->poll_interval == POLL_STOP_TIME)
+			poll_dev->poll_interval = POLL_INTERVAL;
+	}
+	if (mma8x5x_read_data(pdata->client, &data) != 0)
+		goto out;
+	mma8x5x_data_convert(pdata, &data);
+	input_report_abs(poll_dev->input, ABS_X, data.x);
+	input_report_abs(poll_dev->input, ABS_Y, data.y);
+	input_report_abs(poll_dev->input, ABS_Z, data.z);
+	input_sync(poll_dev->input);
+out:
+	mutex_unlock(&pdata->data_lock);
+}
+
+static void mma8x5x_dev_poll(struct input_polled_dev *dev)
+{
+	struct mma8x5x_data *pdata = (struct mma8x5x_data *)dev->private;
+	mma8x5x_report_data(pdata);
+}
+
+static ssize_t mma8x5x_enable_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+	struct i2c_client *client = pdata->client;
+	u8 val;
+	int enable;
+
+	mutex_lock(&pdata->data_lock);
+	val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+	if ((val & 0x01) && pdata->active == MMA_ACTIVED)
+		enable = 1;
+	else
+		enable = 0;
+	mutex_unlock(&pdata->data_lock);
+	return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t mma8x5x_enable_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+	struct i2c_client *client = pdata->client;
+	int ret;
+	unsigned long enable;
+	u8 val = 0;
+	ret = kstrtoul(buf, 10, &enable);
+	if (ret)
+		return ret;
+	mutex_lock(&pdata->data_lock);
+	enable = (enable > 0) ? 1 : 0;
+	if (enable && pdata->active == MMA_STANDBY) {
+		val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+		ret = i2c_smbus_write_byte_data(client,
+				MMA8X5X_CTRL_REG1, val|0x01);
+		if (!ret) {
+			pdata->active = MMA_ACTIVED;
+			printk(KERN_INFO "mma enable setting active\n");
+		}
+	} else if (enable == 0  && pdata->active == MMA_ACTIVED) {
+		val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+		ret = i2c_smbus_write_byte_data(client,
+			MMA8X5X_CTRL_REG1, val & 0xFE);
+		if (!ret) {
+			pdata->active = MMA_STANDBY;
+			printk(KERN_INFO "mma enable setting inactive\n");
+		}
+	}
+	mutex_unlock(&pdata->data_lock);
+	return count;
+}
+static ssize_t mma8x5x_position_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+	int position = 0;
+	mutex_lock(&pdata->data_lock);
+	position = pdata->position ;
+	mutex_unlock(&pdata->data_lock);
+	return snprintf(buf, PAGE_SIZE, "%d\n", position);
+}
+
+static ssize_t mma8x5x_position_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+	int position;
+	int ret;
+	ret = kstrtoint(buf, 10, &position);
+	if (ret)
+		return ret;
+	mutex_lock(&pdata->data_lock);
+	pdata->position = position;
+	mutex_unlock(&pdata->data_lock);
+	return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+		   mma8x5x_enable_show, mma8x5x_enable_store);
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
+		   mma8x5x_position_show, mma8x5x_position_store);
+
+static struct attribute *mma8x5x_attributes[] = {
+	&dev_attr_enable.attr,
+	&dev_attr_position.attr,
+	NULL
+};
+
+static const struct attribute_group mma8x5x_attr_group = {
+	.attrs = mma8x5x_attributes,
+};
+static int mma8x5x_detect(struct i2c_client *client,
+			  struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int chip_id;
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -ENODEV;
+	chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
+	if (!mma8x5x_check_id(chip_id))
+		return -ENODEV;
+	printk(KERN_INFO "check %s i2c address 0x%x\n",
+		mma8x5x_id2name(chip_id), client->addr);
+	strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
+	return 0;
+}
+static int __devinit mma8x5x_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	int result, chip_id;
+	struct input_dev *idev;
+	struct mma8x5x_data *pdata;
+	struct i2c_adapter *adapter;
+	struct input_polled_dev *poll_dev;
+	adapter = to_i2c_adapter(client->dev.parent);
+	/* power on the device */
+	result = mma8x5x_config_regulator(client, 1);
+	if (result)
+		goto err_power_on;
+
+	result = i2c_check_functionality(adapter,
+					 I2C_FUNC_SMBUS_BYTE |
+					 I2C_FUNC_SMBUS_BYTE_DATA);
+	if (!result)
+		goto err_out;
+
+	chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
+
+	if (!mma8x5x_check_id(chip_id)) {
+		dev_err(&client->dev,
+			"read chip ID 0x%x is not equal to 0x%x,0x%x,0x%x,0x%x,0x%x!\n",
+			chip_id, MMA8451_ID, MMA8452_ID, MMA8453_ID,
+			MMA8652_ID, MMA8653_ID);
+		result = -EINVAL;
+		goto err_out;
+	}
+	/* set the private data */
+	pdata = kzalloc(sizeof(struct mma8x5x_data), GFP_KERNEL);
+	if (!pdata) {
+		result = -ENOMEM;
+		dev_err(&client->dev, "alloc data memory error!\n");
+		goto err_out;
+	}
+	/* Initialize the MMA8X5X chip */
+	pdata->client = client;
+	pdata->chip_id = chip_id;
+	pdata->mode = MODE_2G;
+	pdata->position = CONFIG_SENSORS_MMA_POSITION;
+	mutex_init(&pdata->data_lock);
+	i2c_set_clientdata(client, pdata);
+	/* Initialize the MMA8X5X chip */
+	mma8x5x_device_init(client);
+	/* create the input poll device */
+	poll_dev = input_allocate_polled_device();
+	if (!poll_dev) {
+		result = -ENOMEM;
+		dev_err(&client->dev, "alloc poll device failed!\n");
+		goto err_alloc_poll_device;
+	}
+	poll_dev->poll = mma8x5x_dev_poll;
+	poll_dev->poll_interval = POLL_STOP_TIME;
+	poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
+	poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+	poll_dev->private = pdata;
+	idev = poll_dev->input;
+	idev->name = "accelerometer";
+	idev->uniq = mma8x5x_id2name(pdata->chip_id);
+	idev->id.bustype = BUS_I2C;
+	idev->evbit[0] = BIT_MASK(EV_ABS);
+	input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
+	input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
+	input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
+	pdata->poll_dev = poll_dev;
+	result = input_register_polled_device(pdata->poll_dev);
+	if (result) {
+		dev_err(&client->dev, "register poll device failed!\n");
+		goto err_register_polled_device;
+	}
+	result = sysfs_create_group(&idev->dev.kobj, &mma8x5x_attr_group);
+	if (result) {
+		dev_err(&client->dev, "create device file failed!\n");
+		result = -EINVAL;
+		goto err_create_sysfs;
+	}
+	printk(KERN_INFO "mma8x5x device driver probe successfully\n");
+	return 0;
+err_create_sysfs:
+	input_unregister_polled_device(pdata->poll_dev);
+err_register_polled_device:
+	input_free_polled_device(poll_dev);
+err_alloc_poll_device:
+	kfree(pdata);
+err_out:
+	mma8x5x_config_regulator(client, 0);
+err_power_on:
+	return result;
+}
+static int __devexit mma8x5x_remove(struct i2c_client *client)
+{
+	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+	struct input_polled_dev *poll_dev;
+	mma8x5x_device_stop(client);
+	if (pdata) {
+		poll_dev = pdata->poll_dev;
+		input_unregister_polled_device(poll_dev);
+		input_free_polled_device(poll_dev);
+		kfree(pdata);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mma8x5x_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+	if (pdata->active == MMA_ACTIVED)
+		mma8x5x_device_stop(client);
+	return 0;
+}
+
+static int mma8x5x_resume(struct device *dev)
+{
+	int val = 0;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+	if (pdata->active == MMA_ACTIVED) {
+		val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+		i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val|0x01);
+	}
+	return 0;
+
+}
+#endif
+
+static const struct i2c_device_id mma8x5x_id[] = {
+	{"mma8x5x", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mma8x5x_id);
+
+static const struct of_device_id mma8x5x_of_match[] = {
+	{ .compatible = "fsl,mma8x5x", },
+	{ },
+};
+
+static SIMPLE_DEV_PM_OPS(mma8x5x_pm_ops, mma8x5x_suspend, mma8x5x_resume);
+static struct i2c_driver mma8x5x_driver = {
+	.class  = I2C_CLASS_HWMON,
+	.driver = {
+		.name = "mma8x5x",
+		.owner = THIS_MODULE,
+		.pm = &mma8x5x_pm_ops,
+		.of_match_table = mma8x5x_of_match,
+	},
+	.probe = mma8x5x_probe,
+	.remove = __devexit_p(mma8x5x_remove),
+	.id_table = mma8x5x_id,
+	.detect = mma8x5x_detect,
+	.address_list = normal_i2c,
+};
+
+static int __init mma8x5x_init(void)
+{
+	/* register driver */
+	int res;
+
+	res = i2c_add_driver(&mma8x5x_driver);
+	if (res < 0) {
+		printk(KERN_INFO "add mma8x5x i2c driver failed\n");
+		return -ENODEV;
+	}
+	return res;
+}
+
+static void __exit mma8x5x_exit(void)
+{
+	i2c_del_driver(&mma8x5x_driver);
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8X5X 3-Axis Orientation/Motion Detection Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(mma8x5x_init);
+module_exit(mma8x5x_exit);
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 6c64a57..519b7e4 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -43,8 +43,8 @@
 #include <linux/gpio.h>
 #include <linux/input/mpu3050.h>
 #include <linux/regulator/consumer.h>
-
-#define MPU3050_CHIP_ID		0x69
+#include <linux/of_gpio.h>
+#include <mach/gpiomux.h>
 
 #define MPU3050_AUTO_DELAY	1000
 
@@ -124,6 +124,8 @@
 	u32    use_poll;
 	u32    poll_interval;
 	u32    dlpf_index;
+	u32    enable_gpio;
+	u32    enable;
 };
 
 struct sensor_regulator {
@@ -138,6 +140,11 @@
 	{NULL, "vlogic", 1800000, 1800000},
 };
 
+static const int mpu3050_chip_ids[] = {
+	0x68,
+	0x69,
+};
+
 struct dlpf_cfg_tb {
 	u8  cfg;	/* cfg index */
 	u32 lpf_bw;	/* low pass filter bandwidth in Hz */
@@ -293,11 +300,42 @@
 	return size;
 }
 
-static struct device_attribute attributes[] = {
+/**
+ *  Set/get enable function is just needed by sensor HAL.
+ *  Normally, the open function does all the initialization
+ *  and power work. And close undo that open does.
+ *  Just keeping the function simple.
+ */
 
+static ssize_t mpu3050_attr_set_enable(struct device *dev,
+			struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+	sensor->enable = (u32)val;
+
+	return count;
+}
+
+static ssize_t mpu3050_attr_get_enable(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+
+	return snprintf(buf, 4, "%d\n", sensor->enable);
+}
+
+static struct device_attribute attributes[] = {
 	__ATTR(pollrate_ms, 0664,
 		mpu3050_attr_get_polling_rate,
 		mpu3050_attr_set_polling_rate),
+	__ATTR(enable, 0644,
+		mpu3050_attr_get_enable,
+		mpu3050_attr_set_enable),
 };
 
 static int create_sysfs_interfaces(struct device *dev)
@@ -390,10 +428,12 @@
 static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
 {
 	u8 value;
+	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
 
 	if (val) {
 		mpu3050_config_regulator(client, 1);
 		udelay(10);
+		gpio_set_value(sensor->enable_gpio, 1);
 	}
 
 	value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
@@ -404,6 +444,8 @@
 
 	if (!val) {
 		udelay(10);
+		gpio_set_value(sensor->enable_gpio, 0);
+		udelay(10);
 		mpu3050_config_regulator(client, 0);
 	}
 }
@@ -550,6 +592,37 @@
 
 	return 0;
 }
+#ifdef CONFIG_OF
+static int mpu3050_parse_dt(struct device *dev,
+			struct mpu3050_gyro_platform_data *pdata)
+{
+	int rc = 0;
+
+	rc = of_property_read_u32(dev->of_node, "invn,poll-interval",
+				&pdata->poll_interval);
+	if (rc) {
+		dev_err(dev, "Failed to read poll-interval\n");
+		return rc;
+	}
+
+	/* check gpio_int later, if it is invalid, just use poll */
+	pdata->gpio_int = of_get_named_gpio_flags(dev->of_node,
+				"invn,gpio-int", 0, NULL);
+
+	pdata->gpio_en = of_get_named_gpio_flags(dev->of_node,
+				"invn,gpio-en", 0, NULL);
+	if (!gpio_is_valid(pdata->gpio_en))
+		return -EINVAL;
+
+	return 0;
+}
+#else
+static int mpu3050_parse_dt(struct device *dev,
+			struct mpu3050_gyro_platform_data *pdata)
+{
+	return -EINVAL;
+}
+#endif
 
 /**
  *	mpu3050_probe	-	device detection callback
@@ -566,8 +639,10 @@
 {
 	struct mpu3050_sensor *sensor;
 	struct input_dev *idev;
+	struct mpu3050_gyro_platform_data *pdata;
 	int ret;
 	int error;
+	u32 i;
 
 	sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
 	idev = input_allocate_device();
@@ -580,10 +655,29 @@
 	sensor->client = client;
 	sensor->dev = &client->dev;
 	sensor->idev = idev;
-	sensor->platform_data = client->dev.platform_data;
 	i2c_set_clientdata(client, sensor);
+
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+			sizeof(struct mpu3050_gyro_platform_data), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev, "Failed to allcated memory\n");
+			error = -ENOMEM;
+			goto err_free_mem;
+		}
+		ret = mpu3050_parse_dt(&client->dev, pdata);
+		if (ret) {
+			dev_err(&client->dev, "Failed to parse device tree\n");
+			error = ret;
+			goto err_free_mem;
+		}
+	} else
+		pdata = client->dev.platform_data;
+	sensor->platform_data = pdata;
+
 	if (sensor->platform_data) {
 		u32 interval = sensor->platform_data->poll_interval;
+		sensor->enable_gpio = sensor->platform_data->gpio_en;
 
 		if ((interval < MPU3050_MIN_POLL_INTERVAL) ||
 			(interval > MPU3050_MAX_POLL_INTERVAL))
@@ -592,6 +686,12 @@
 			sensor->poll_interval = interval;
 	} else {
 		sensor->poll_interval = MPU3050_DEFAULT_POLL_INTERVAL;
+		sensor->enable_gpio = -EINVAL;
+	}
+
+	if (gpio_is_valid(sensor->enable_gpio)) {
+		ret = gpio_request(sensor->enable_gpio, "GYRO_EN_PM");
+		gpio_direction_output(sensor->enable_gpio, 1);
 	}
 
 	mpu3050_set_power_mode(client, 1);
@@ -604,7 +704,11 @@
 		goto err_free_mem;
 	}
 
-	if (ret != MPU3050_CHIP_ID) {
+	for (i = 0; i < ARRAY_SIZE(mpu3050_chip_ids); i++)
+		if (ret == mpu3050_chip_ids[i])
+			break;
+
+	if (i == ARRAY_SIZE(mpu3050_chip_ids)) {
 		dev_err(&client->dev, "unsupported chip id\n");
 		error = -ENXIO;
 		goto err_free_mem;
@@ -617,7 +721,7 @@
 	idev->open = mpu3050_input_open;
 	idev->close = mpu3050_input_close;
 
-	__set_bit(EV_ABS, idev->evbit);
+	input_set_capability(idev, EV_ABS, ABS_MISC);
 	input_set_abs_params(idev, ABS_X,
 			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
 	input_set_abs_params(idev, ABS_Y,
@@ -657,6 +761,11 @@
 				__func__, sensor->platform_data->gpio_int);
 				goto err_free_gpio;
 			}
+			client->irq = gpio_to_irq(
+					sensor->platform_data->gpio_int);
+		} else {
+			ret = -EINVAL;
+			goto err_pm_set_suspended;
 		}
 
 		error = request_threaded_irq(client->irq,
@@ -677,14 +786,20 @@
 		goto err_free_irq;
 	}
 
-	error = create_sysfs_interfaces(&client->dev);
+	error = create_sysfs_interfaces(&idev->dev);
 	if (error < 0) {
 		dev_err(&client->dev, "failed to create sysfs\n");
 		goto err_input_cleanup;
 	}
 
-	pm_runtime_enable(&client->dev);
-	pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
+	if (sensor->use_poll)
+		schedule_delayed_work(&sensor->input_work,
+				msecs_to_jiffies(sensor->poll_interval));
+	else
+		i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
+				MPU3050_ACTIVE_LOW |
+				MPU3050_OPEN_DRAIN |
+				MPU3050_RAW_RDY_EN);
 
 	return 0;
 
@@ -722,6 +837,8 @@
 		free_irq(client->irq, sensor);
 
 	remove_sysfs_interfaces(&client->dev);
+	if (gpio_is_valid(sensor->enable_gpio))
+		gpio_free(sensor->enable_gpio);
 	input_unregister_device(sensor->idev);
 
 	kfree(sensor);
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 8dbac64..1041c9e8 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -308,7 +308,7 @@
 			event->pressure = 0;
 		}
 
-		input_mt_slot(data->input_dev, i);
+		input_mt_slot(data->input_dev, event->finger_id[i]);
 		input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
 					!!event->pressure);
 
@@ -317,10 +317,6 @@
 					 event->x[i]);
 			input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
 					 event->y[i]);
-			input_report_abs(data->input_dev, ABS_MT_PRESSURE,
-					 event->pressure);
-			input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
-					 event->finger_id[i]);
 			input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
 					 event->pressure);
 		}
@@ -493,7 +489,7 @@
 static int ft5x06_ts_suspend(struct device *dev)
 {
 	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
-	char txbuf[2];
+	char txbuf[2], i;
 
 	if (data->loading_fw) {
 		dev_info(dev, "Firmware loading in process...\n");
@@ -507,6 +503,14 @@
 
 	disable_irq(data->client->irq);
 
+	/* release all touches */
+	for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
+		input_mt_slot(data->input_dev, i);
+		input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
+	}
+	input_report_key(data->input_dev, BTN_TOUCH, 0);
+	input_sync(data->input_dev);
+
 	if (gpio_is_valid(data->pdata->reset_gpio)) {
 		txbuf[0] = FT_REG_PMODE;
 		txbuf[1] = FT_PMODE_HIBERNATE;
@@ -1231,7 +1235,6 @@
 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
 			     pdata->y_max, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
 
 	err = input_register_device(input_dev);
 	if (err) {
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 2c2b339..189418a 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -246,6 +246,8 @@
 				enum dmx_tsp_format_t tsp_format);
 	int (*set_secure_mode)(struct dmx_ts_feed *feed,
 				struct dmx_secure_mode *sec_mode);
+	int (*set_cipher_ops)(struct dmx_ts_feed *feed,
+				struct dmx_cipher_operations *cipher_ops);
 	int (*oob_command) (struct dmx_ts_feed *feed,
 			struct dmx_oob_command *cmd);
 	int (*ts_insertion_init)(struct dmx_ts_feed *feed);
@@ -301,6 +303,8 @@
 			u32 bytes_num);
 	int (*set_secure_mode)(struct dmx_section_feed *feed,
 				struct dmx_secure_mode *sec_mode);
+	int (*set_cipher_ops)(struct dmx_section_feed *feed,
+				struct dmx_cipher_operations *cipher_ops);
 	int (*oob_command) (struct dmx_section_feed *feed,
 				struct dmx_oob_command *cmd);
 	int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
@@ -388,6 +392,7 @@
 	struct dmx_frontend* frontend;    /* Front-end connected to the demux */
 	void* priv;                  /* Pointer to private data of the API client */
 	struct data_buffer dvr_input; /* DVR input buffer */
+	int dvr_input_protected;
 	struct dentry *debugfs_demux_dir; /* debugfs dir */
 
 	int (*open) (struct dmx_demux* demux);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 28e8092..a1cac54 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -566,6 +566,7 @@
 	int bytes_written = 0;
 	size_t split;
 	size_t tsp_size;
+	u8 *data_start;
 	struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
 	todo = dvr_cmd->cmd.data_feed_count;
 
@@ -578,15 +579,15 @@
 		/* wait for input */
 		ret = wait_event_interruptible(
 			src->queue,
-			(dvb_ringbuffer_avail(src) >= tsp_size) || (!src->data)
-			|| (dmxdev->dvr_in_exit) || (src->error));
+			(dvb_ringbuffer_avail(src) >= tsp_size) ||
+			dmxdev->dvr_in_exit || src->error);
 
 		if (ret < 0)
 			break;
 
 		spin_lock(&dmxdev->dvr_in_lock);
 
-		if (!src->data || dmxdev->exit || dmxdev->dvr_in_exit) {
+		if (dmxdev->exit || dmxdev->dvr_in_exit) {
 			spin_unlock(&dmxdev->dvr_in_lock);
 			ret = -ENODEV;
 			break;
@@ -609,12 +610,20 @@
 		 * Lock on DVR buffer is released before calling to
 		 * write, if DVR was released meanwhile, dvr_in_exit is
 		 * prompted. Lock is acquired when updating the read pointer
-		 * again to preserve read/write pointers consistency
+		 * again to preserve read/write pointers consistency.
+		 *
+		 * In protected input mode, DVR input buffer is not mapped
+		 * to kernel memory. Underlying demux implementation
+		 * should trigger HW to read from DVR input buffer
+		 * based on current read offset.
 		 */
 		if (split > 0) {
+			data_start = (dmxdev->demux->dvr_input_protected) ?
+						NULL : (src->data + src->pread);
+
 			spin_unlock(&dmxdev->dvr_in_lock);
 			ret = dmxdev->demux->write(dmxdev->demux,
-						src->data + src->pread,
+						data_start,
 						split);
 
 			if (ret < 0) {
@@ -641,9 +650,12 @@
 			}
 		}
 
+		data_start = (dmxdev->demux->dvr_input_protected) ?
+			NULL : (src->data + src->pread);
+
 		spin_unlock(&dmxdev->dvr_in_lock);
 		ret = dmxdev->demux->write(dmxdev->demux,
-			src->data + src->pread, todo);
+			data_start, todo);
 
 		if (ret < 0) {
 			printk(KERN_ERR "dmxdev: dvr write error %d\n",
@@ -708,8 +720,7 @@
 
 			ret = dvb_dvr_feed_cmd(dmxdev, &dvr_cmd);
 			if (ret < 0) {
-				printk(KERN_ERR
-					"%s: DVR data feed failed, ret=%d\n",
+				dprintk("%s: DVR data feed failed, ret=%d\n",
 					__func__, ret);
 				continue;
 			}
@@ -825,6 +836,7 @@
 
 		dmxdev->demux->dvr_input.priv_handle = NULL;
 		dmxdev->demux->dvr_input.ringbuff = &dmxdev->dvr_input_buffer;
+		dmxdev->demux->dvr_input_protected = 0;
 		mem = vmalloc(DVR_CMDS_BUFFER_SIZE);
 		if (!mem) {
 			vfree(dmxdev->dvr_input_buffer.data);
@@ -936,7 +948,8 @@
 		if ((dmxdev->dvr_input_buffer_mode ==
 			DMX_BUFFER_MODE_EXTERNAL) &&
 			(dmxdev->demux->dvr_input.priv_handle)) {
-			dmxdev->demux->unmap_buffer(dmxdev->demux,
+			if (!dmxdev->demux->dvr_input_protected)
+				dmxdev->demux->unmap_buffer(dmxdev->demux,
 					dmxdev->demux->dvr_input.priv_handle);
 			dmxdev->demux->dvr_input.priv_handle = NULL;
 		}
@@ -1130,8 +1143,8 @@
 	for (todo = count; todo > 0; todo -= ret) {
 		ret = wait_event_interruptible(src->queue,
 			(dvb_ringbuffer_free(src)) ||
-			(!src->data) || (!cmdbuf->data) ||
-			(src->error != 0) || (dmxdev->dvr_in_exit));
+			!src->data || !cmdbuf->data ||
+			(src->error != 0) || dmxdev->dvr_in_exit);
 
 		if (ret < 0)
 			return ret;
@@ -1314,6 +1327,7 @@
 	enum dmx_buffer_mode *buffer_mode;
 	void **buff_handle;
 	void *oldmem;
+	int *is_protected;
 
 	if ((mode != DMX_BUFFER_MODE_INTERNAL) &&
 		(mode != DMX_BUFFER_MODE_EXTERNAL))
@@ -1328,11 +1342,13 @@
 		lock = &dmxdev->lock;
 		buffer_mode = &dmxdev->dvr_buffer_mode;
 		buff_handle = &dmxdev->dvr_priv_buff_handle;
+		is_protected = NULL;
 	} else {
 		buf = &dmxdev->dvr_input_buffer;
 		lock = &dmxdev->dvr_in_lock;
 		buffer_mode = &dmxdev->dvr_input_buffer_mode;
 		buff_handle = &dmxdev->demux->dvr_input.priv_handle;
+		is_protected = &dmxdev->demux->dvr_input_protected;
 	}
 
 	if (mode == *buffer_mode)
@@ -1353,6 +1369,9 @@
 			*buff_handle = NULL;
 		}
 
+		if (is_protected)
+			*is_protected = 0;
+
 		/* set default internal buffer */
 		dvb_dvr_set_buffer_size(dmxdev, f_flags, DVR_BUFFER_SIZE);
 	} else if (oldmem) {
@@ -1372,31 +1391,56 @@
 	void **buff_handle;
 	void *newmem;
 	void *oldmem;
+	int *is_protected;
+	struct dmx_caps caps;
+
+	if (dmxdev->demux->get_caps)
+		dmxdev->demux->get_caps(dmxdev->demux, &caps);
+	else
+		caps.caps = 0;
 
 	if ((f_flags & O_ACCMODE) == O_RDONLY) {
 		buf = &dmxdev->dvr_buffer;
 		lock = &dmxdev->lock;
 		buffer_mode = dmxdev->dvr_buffer_mode;
 		buff_handle = &dmxdev->dvr_priv_buff_handle;
+		is_protected = NULL;
 	} else {
 		buf = &dmxdev->dvr_input_buffer;
 		lock = &dmxdev->dvr_in_lock;
 		buffer_mode = dmxdev->dvr_input_buffer_mode;
 		buff_handle = &dmxdev->demux->dvr_input.priv_handle;
+		is_protected = &dmxdev->demux->dvr_input_protected;
+		if (!(caps.caps & DMX_CAP_SECURED_INPUT_PLAYBACK) &&
+			dmx_buffer->is_protected)
+			return -EINVAL;
 	}
 
-	if ((!dmx_buffer->size) ||
+	if (!dmx_buffer->size ||
 		(buffer_mode == DMX_BUFFER_MODE_INTERNAL))
 		return -EINVAL;
 
 	oldmem = *buff_handle;
-	if (dmxdev->demux->map_buffer(dmxdev->demux, dmx_buffer,
-				buff_handle, &newmem))
-		return -ENOMEM;
+
+	/*
+	 * Protected buffer is relevant only for DVR input buffer
+	 * when DVR device is opened for write. In such case,
+	 * buffer is mapped only if the buffer is not protected one.
+	 */
+	if (!is_protected || !dmx_buffer->is_protected) {
+		if (dmxdev->demux->map_buffer(dmxdev->demux, dmx_buffer,
+					buff_handle, &newmem))
+			return -ENOMEM;
+	} else {
+		newmem = NULL;
+		*buff_handle = NULL;
+	}
 
 	spin_lock_irq(lock);
 	buf->data = newmem;
 	buf->size = dmx_buffer->size;
+	if (is_protected)
+		*is_protected = dmx_buffer->is_protected;
 	dvb_ringbuffer_reset(buf);
 	spin_unlock_irq(lock);
 
@@ -1717,19 +1761,20 @@
 static int dvb_dmxdev_set_source(struct dmxdev_filter *dmxdevfilter,
 					dmx_source_t *source)
 {
+	int ret = 0;
 	struct dmxdev *dev;
 
 	if (dmxdevfilter->state == DMXDEV_STATE_GO)
 		return -EBUSY;
 
 	dev = dmxdevfilter->dev;
-
-	dev->source = *source;
-
 	if (dev->demux->set_source)
-		return dev->demux->set_source(dev->demux, source);
+		ret = dev->demux->set_source(dev->demux, source);
 
-	return 0;
+	if (!ret)
+		dev->source = *source;
+
+	return ret;
 }
 
 static int dvb_dmxdev_reuse_decoder_buf(struct dmxdev_filter *dmxdevfilter,
@@ -3105,7 +3150,10 @@
 		tsfeed->set_tsp_out_format(tsfeed, filter->dmx_tsp_format);
 
 	if (tsfeed->set_secure_mode)
-		tsfeed->set_secure_mode(tsfeed, &feed->sec_mode);
+		tsfeed->set_secure_mode(tsfeed, &filter->sec_mode);
+
+	if (tsfeed->set_cipher_ops)
+		tsfeed->set_cipher_ops(tsfeed, &feed->cipher_ops);
 
 	if ((para->pes_type == DMX_PES_VIDEO0) ||
 	    (para->pes_type == DMX_PES_VIDEO1) ||
@@ -3265,7 +3313,11 @@
 
 			if ((*secfeed)->set_secure_mode)
 				(*secfeed)->set_secure_mode(*secfeed,
-					&filter->feed.sec.sec_mode);
+					&filter->sec_mode);
+
+			if ((*secfeed)->set_cipher_ops)
+				(*secfeed)->set_cipher_ops(*secfeed,
+					&filter->feed.sec.cipher_ops);
 		} else {
 			dvb_dmxdev_feed_stop(filter);
 		}
@@ -3434,6 +3486,8 @@
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 	init_timer(&dmxdevfilter->timer);
 
+	dmxdevfilter->sec_mode.is_secured = 0;
+
 	INIT_LIST_HEAD(&dmxdevfilter->insertion_buffers);
 
 	dmxdevfilter->dmx_tsp_format = DMX_TSP_FORMAT_188;
@@ -3513,7 +3567,7 @@
 		return -ENOMEM;
 
 	feed->pid = pid;
-	feed->sec_mode.is_secured = 0;
+	feed->cipher_ops.operations_count = 0;
 	feed->idx_params.enable = 0;
 	list_add(&feed->next, &filter->feed.ts);
 
@@ -3568,7 +3622,7 @@
 	memcpy(&dmxdevfilter->params.sec,
 	       params, sizeof(struct dmx_sct_filter_params));
 	invert_mode(&dmxdevfilter->params.sec.filter);
-	dmxdevfilter->feed.sec.sec_mode.is_secured = 0;
+	dmxdevfilter->feed.sec.cipher_ops.operations_count = 0;
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 
 	if (params->flags & DMX_IMMEDIATE_START)
@@ -3582,43 +3636,78 @@
 	struct dmxdev_filter *filter,
 	struct dmx_secure_mode *sec_mode)
 {
+	if (!dmxdev || !filter || !sec_mode)
+		return -EINVAL;
+
+	if (filter->state == DMXDEV_STATE_GO) {
+		printk(KERN_ERR "%s: invalid filter state\n", __func__);
+		return -EBUSY;
+	}
+
+	dprintk(KERN_DEBUG "%s: secure=%d\n", __func__, sec_mode->is_secured);
+
+	filter->sec_mode = *sec_mode;
+
+	return 0;
+}
+
+static int dvb_dmxdev_set_cipher(struct dmxdev *dmxdev,
+	struct dmxdev_filter *filter,
+	struct dmx_cipher_operations *cipher_ops)
+{
 	struct dmxdev_feed *feed;
 	struct dmxdev_feed *ts_feed = NULL;
 	struct dmxdev_sec_feed *sec_feed = NULL;
+	struct dmx_caps caps;
 
-	if (NULL == dmxdev || NULL == filter || NULL == sec_mode)
+	if (!dmxdev || !dmxdev->demux->get_caps)
 		return -EINVAL;
 
+	dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+	if (!filter || !cipher_ops ||
+		(cipher_ops->operations_count > caps.num_cipher_ops) ||
+		(cipher_ops->operations_count >
+		 DMX_MAX_CIPHER_OPERATIONS_COUNT))
+		return -EINVAL;
+
+	dprintk(KERN_DEBUG "%s: pid=%d, operations=%d\n", __func__,
+		cipher_ops->pid, cipher_ops->operations_count);
+
 	if (filter->state < DMXDEV_STATE_SET ||
 		filter->state > DMXDEV_STATE_GO) {
 		printk(KERN_ERR "%s: invalid filter state\n", __func__);
 		return -EPERM;
 	}
-	dprintk(KERN_DEBUG "%s: key_id=%d, secure=%d, looking for pid=%d\n",
-		__func__, sec_mode->key_ladder_id, sec_mode->is_secured,
-		sec_mode->pid);
+
+	if (!filter->sec_mode.is_secured && cipher_ops->operations_count) {
+		printk(KERN_ERR "%s: secure mode must be enabled to set cipher ops\n",
+			__func__);
+		return -EPERM;
+	}
+
 	switch (filter->type) {
 	case DMXDEV_TYPE_PES:
 		list_for_each_entry(feed, &filter->feed.ts, next) {
-			if (feed->pid == sec_mode->pid) {
+			if (feed->pid == cipher_ops->pid) {
 				ts_feed = feed;
-				ts_feed->sec_mode = *sec_mode;
+				ts_feed->cipher_ops = *cipher_ops;
 				if (filter->state == DMXDEV_STATE_GO &&
-					ts_feed->ts->set_secure_mode)
-					ts_feed->ts->set_secure_mode(
-						ts_feed->ts, sec_mode);
+					ts_feed->ts->set_cipher_ops)
+					ts_feed->ts->set_cipher_ops(
+						ts_feed->ts, cipher_ops);
 				break;
 			}
 		}
 		break;
 	case DMXDEV_TYPE_SEC:
-		if (filter->params.sec.pid == sec_mode->pid) {
+		if (filter->params.sec.pid == cipher_ops->pid) {
 			sec_feed = &filter->feed.sec;
-			sec_feed->sec_mode = *sec_mode;
+			sec_feed->cipher_ops = *cipher_ops;
 			if (filter->state == DMXDEV_STATE_GO &&
-				sec_feed->feed->set_secure_mode)
-				sec_feed->feed->set_secure_mode(sec_feed->feed,
-						sec_mode);
+				sec_feed->feed->set_cipher_ops)
+				sec_feed->feed->set_cipher_ops(sec_feed->feed,
+						cipher_ops);
 		}
 		break;
 
@@ -3628,7 +3717,7 @@
 
 	if (!ts_feed && !sec_feed) {
 		printk(KERN_ERR "%s: pid %d is undefined for this filter\n",
-			__func__, sec_mode->pid);
+			__func__, cipher_ops->pid);
 		return -EINVAL;
 	}
 
@@ -4029,6 +4118,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_SET_CIPHER:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+		ret = dvb_dmxdev_set_cipher(dmxdev, dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	case DMX_REUSE_DECODER_BUFFER:
 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 			mutex_unlock(&dmxdev->mutex);
@@ -4384,13 +4482,12 @@
 					buffer_status.fullness);
 				seq_printf(s, "error: %d, ",
 					buffer_status.error);
-				seq_printf(s, "scramble: %d\n",
-					scrambling_bits.value);
-
-			} else {
-				seq_printf(s, "scramble: %d\n",
-					scrambling_bits.value);
 			}
+
+			seq_printf(s, "scramble: %d, ",
+				scrambling_bits.value);
+			seq_printf(s, "secured: %d\n",
+				filter->sec_mode.is_secured);
 		}
 	}
 
@@ -4425,6 +4522,7 @@
 		return -ENOMEM;
 
 	dmxdev->playback_mode = DMX_PB_MODE_PUSH;
+	dmxdev->demux->dvr_input_protected = 0;
 
 	mutex_init(&dmxdev->mutex);
 	spin_lock_init(&dmxdev->lock);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 4e306e8..6747ca7 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -58,15 +58,15 @@
 
 struct dmxdev_feed {
 	u16 pid;
-	struct dmx_secure_mode sec_mode;
 	struct dmx_indexing_params idx_params;
+	struct dmx_cipher_operations cipher_ops;
 	struct dmx_ts_feed *ts;
 	struct list_head next;
 };
 
 struct dmxdev_sec_feed {
-	struct dmx_secure_mode sec_mode;
 	struct dmx_section_feed *feed;
+	struct dmx_cipher_operations cipher_ops;
 };
 
 #define DMX_EVENT_QUEUE_SIZE	500 /* number of events */
@@ -182,6 +182,8 @@
 	int todo;
 	u8 secheader[3];
 
+	struct dmx_secure_mode sec_mode;
+
 	/* Decoder buffer(s) related */
 	struct dmx_decoder_buffers decoder_buffers;
 };
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index bbf2470..692a04e 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -2262,19 +2262,36 @@
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	if (dvbdmxfeed->state == DMX_STATE_GO) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EBUSY;
+	}
+
+	dvbdmxfeed->secure_mode = *secure_mode;
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+static int dmx_ts_set_cipher_ops(struct dmx_ts_feed *feed,
+				struct dmx_cipher_operations *cipher_ops)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	int ret = 0;
 
-	mutex_lock(&dvbdmx->mutex);
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
 
 	if ((dvbdmxfeed->state == DMX_STATE_GO) &&
-		dvbdmxfeed->demux->set_secure_mode) {
-		ret = dvbdmxfeed->demux->set_secure_mode(dvbdmxfeed,
-			secure_mode);
-		if (!ret)
-			dvbdmxfeed->secure_mode = *secure_mode;
-	} else {
-		dvbdmxfeed->secure_mode = *secure_mode;
-	}
+		dvbdmx->set_cipher_op)
+		ret = dvbdmx->set_cipher_op(dvbdmxfeed, cipher_ops);
+
+	if (!ret)
+		dvbdmxfeed->cipher_ops = *cipher_ops;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return ret;
@@ -2481,6 +2498,7 @@
 	(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
+	(*ts_feed)->set_cipher_ops = dmx_ts_set_cipher_ops;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
 	(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
 	(*ts_feed)->ts_insertion_init = NULL;
@@ -2724,15 +2742,38 @@
 
 	mutex_lock(&dvbdmx->mutex);
 
-	dvbdmxfeed->secure_mode = *secure_mode;
-	if ((dvbdmxfeed->state == DMX_STATE_GO) &&
-		dvbdmxfeed->demux->set_secure_mode)
-		dvbdmxfeed->demux->set_secure_mode(dvbdmxfeed, secure_mode);
+	if (dvbdmxfeed->state == DMX_STATE_GO) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EBUSY;
+	}
 
+	dvbdmxfeed->secure_mode = *secure_mode;
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
 }
 
+static int dmx_section_set_cipher_ops(struct dmx_section_feed *feed,
+				struct dmx_cipher_operations *cipher_ops)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	if ((dvbdmxfeed->state == DMX_STATE_GO) &&
+		dvbdmx->set_cipher_op) {
+		ret = dvbdmx->set_cipher_op(dvbdmxfeed, cipher_ops);
+	}
+
+	if (!ret)
+		dvbdmxfeed->cipher_ops = *cipher_ops;
+
+	mutex_unlock(&dvbdmx->mutex);
+	return ret;
+}
+
 static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
 					   struct dmx_section_filter *filter)
 {
@@ -2875,6 +2916,7 @@
 	(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
 	(*feed)->notify_data_read = NULL;
 	(*feed)->set_secure_mode = dmx_section_set_secure_mode;
+	(*feed)->set_cipher_ops = dmx_section_set_cipher_ops;
 	(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
 	(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
 
@@ -2939,8 +2981,10 @@
 {
 	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
-	if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
+	if (!demux->frontend || !buf || demux->dvr_input_protected ||
+		(demux->frontend->source != DMX_MEMORY_FE)) {
 		return -EINVAL;
+	}
 
 	dvb_dmx_swfilter_format(dvbdemux, buf, count, dvbdemux->tsp_format);
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index aeafa57..835e7b8 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -176,6 +176,7 @@
 	int buffer_size;
 	enum dmx_tsp_format_t tsp_out_format;
 	struct dmx_secure_mode secure_mode;
+	struct dmx_cipher_operations cipher_ops;
 
 	struct timespec timeout;
 	struct dvb_demux_filter *filter;
@@ -233,8 +234,8 @@
 				struct dmx_buffer_status *dmx_buffer_status);
 	int (*reuse_decoder_buffer)(struct dvb_demux_feed *feed,
 				int cookie);
-	int (*set_secure_mode)(struct dvb_demux_feed *feed,
-				struct dmx_secure_mode *secure_mode);
+	int (*set_cipher_op)(struct dvb_demux_feed *feed,
+				struct dmx_cipher_operations *cipher_ops);
 	u32 (*check_crc32)(struct dvb_demux_feed *feed,
 			    const u8 *buf, size_t len);
 	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 23e05e2..75b75ea 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -3650,16 +3650,18 @@
 	 * If pid has a key ladder id associated, we need to
 	 * set it to SDMX.
 	 */
-	if (dvbdmx_feed->secure_mode.is_secured)  {
+	if (dvbdmx_feed->secure_mode.is_secured &&
+		dvbdmx_feed->cipher_ops.operations_count) {
 		MPQ_DVB_DBG_PRINT(
-				"%s: set key-ladder %d to PID %d\n",
-				__func__,
-				dvbdmx_feed->secure_mode.key_ladder_id,
-				dvbdmx_feed->secure_mode.pid);
-		ret = sdmx_set_kl_ind(
-			mpq_demux->sdmx_session_handle,
-			dvbdmx_feed->secure_mode.pid,
-			dvbdmx_feed->secure_mode.key_ladder_id);
+			"%s: set key-ladder %d to PID %d\n",
+			__func__,
+			dvbdmx_feed->cipher_ops.operations[0].key_ladder_id,
+			dvbdmx_feed->cipher_ops.pid);
+
+		ret = sdmx_set_kl_ind(mpq_demux->sdmx_session_handle,
+			dvbdmx_feed->cipher_ops.pid,
+			dvbdmx_feed->cipher_ops.operations[0].key_ladder_id);
+
 		if (ret) {
 			MPQ_DVB_ERR_PRINT(
 				"%s: FAILED to set key ladder, ret=%d\n",
@@ -3789,14 +3791,14 @@
 /**
  * Note: Called only when filter is in "GO" state - after feed has been started.
  */
-int mpq_dmx_set_secure_mode(struct dvb_demux_feed *feed,
-	struct dmx_secure_mode *sec_mode)
+int mpq_dmx_set_cipher_ops(struct dvb_demux_feed *feed,
+		struct dmx_cipher_operations *cipher_ops)
 {
 	struct mpq_feed *mpq_feed;
 	struct mpq_demux *mpq_demux;
 	int ret = 0;
 
-	if (!feed || !feed->priv || !sec_mode) {
+	if (!feed || !feed->priv || !cipher_ops) {
 		MPQ_DVB_ERR_PRINT(
 			"%s: invalid parameters\n",
 			__func__);
@@ -3804,37 +3806,45 @@
 	}
 
 	MPQ_DVB_DBG_PRINT("%s(%d, %d, %d)\n",
-		__func__, sec_mode->pid,
-		sec_mode->is_secured,
-		sec_mode->key_ladder_id);
+		__func__, cipher_ops->pid,
+		cipher_ops->operations_count,
+		cipher_ops->operations[0].key_ladder_id);
+
+	if ((cipher_ops->operations_count > 1) ||
+		(cipher_ops->operations_count &&
+		 cipher_ops->operations[0].encrypt)) {
+		MPQ_DVB_ERR_PRINT(
+			"%s: Invalid cipher operations, count=%d, encrypt=%d\n",
+			__func__, cipher_ops->operations_count,
+			cipher_ops->operations[0].encrypt);
+		return -EINVAL;
+	}
+
+	if (!feed->secure_mode.is_secured) {
+		/*
+		 * Filter is not configured as secured, setting cipher
+		 * operations is not allowed.
+		 */
+		MPQ_DVB_ERR_PRINT(
+			"%s: Cannot set cipher operations to non-secure filter\n",
+			__func__);
+		return -EPERM;
+	}
 
 	mpq_feed = feed->priv;
 	mpq_demux = mpq_feed->mpq_demux;
 
 	mutex_lock(&mpq_demux->mutex);
 
-	if (feed->secure_mode.is_secured != sec_mode->is_secured) {
-		/*
-		 * Switching between secure & non-secure mode is not allowed
-		 * while filter is running
-		 */
-		MPQ_DVB_ERR_PRINT(
-			"%s: Cannot switch between secure mode while filter is running\n",
-			__func__);
-		mutex_unlock(&mpq_demux->mutex);
-		return -EPERM;
-	}
-
 	/*
 	 * Feed is running in secure mode, this secure mode request is to
 	 * update the key ladder id
 	 */
-	if (feed->secure_mode.pid == sec_mode->pid && sec_mode->is_secured &&
-		feed->secure_mode.key_ladder_id != sec_mode->key_ladder_id &&
-		mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) {
+	if ((mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) &&
+		cipher_ops->operations_count) {
 		ret = sdmx_set_kl_ind(mpq_demux->sdmx_session_handle,
-			sec_mode->pid,
-			sec_mode->key_ladder_id);
+			cipher_ops->pid,
+			cipher_ops->operations[0].key_ladder_id);
 		if (ret) {
 			MPQ_DVB_ERR_PRINT(
 				"%s: FAILED to set key ladder, ret=%d\n",
@@ -3847,7 +3857,7 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(mpq_dmx_set_secure_mode);
+EXPORT_SYMBOL(mpq_dmx_set_cipher_ops);
 
 static void mpq_sdmx_prepare_filter_status(struct mpq_demux *mpq_demux,
 	struct sdmx_filter_status *filter_sts,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index 31fd9b5..f095e00 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -654,15 +654,19 @@
 void mpq_dmx_update_hw_statistics(struct mpq_demux *mpq_demux);
 
 /**
- * mpq_dmx_set_secure_mode - Handles set secure mode command from demux device
+ * mpq_dmx_set_cipher_ops - Handles setting of cipher operations
  *
- * @feed: The feed to set its secure mode
- * @sec_mode: Secure mode details (key ladder info)
+ * @feed: The feed to set its cipher operations
+ * @cipher_ops: Cipher operations to be set
+ *
+ * This common function handles only the case when working with
+ * secure-demux. When working with secure demux a single decrypt cipher
+ * operation is allowed.
  *
  * Return error code
-*/
-int mpq_dmx_set_secure_mode(struct dvb_demux_feed *feed,
-		struct dmx_secure_mode *secure_mode);
+ */
+int mpq_dmx_set_cipher_ops(struct dvb_demux_feed *feed,
+		struct dmx_cipher_operations *cipher_ops);
 
 /**
  * mpq_dmx_convert_tts - Convert timestamp attached by HW to each TS
@@ -673,7 +677,7 @@
  * @timestampIn27Mhz: Timestamp result in 27MHz
  *
  * Return error code
-*/
+ */
 void mpq_dmx_convert_tts(struct dvb_demux_feed *feed,
 		const u8 timestamp[TIMESTAMP_LEN],
 		u64 *timestampIn27Mhz);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 5daa842..40445b0 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -561,6 +561,7 @@
 	caps->max_bitrate = 144;
 	caps->demod_input_max_bitrate = 72;
 	caps->memory_input_max_bitrate = 72;
+	caps->num_cipher_ops = 0;
 
 	/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
 	caps->max_stc = (u64)0xFFFFFF * 256;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 5bd008d..940a4bc 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1627,6 +1627,7 @@
 	caps->max_bitrate = 192;
 	caps->demod_input_max_bitrate = 96;
 	caps->memory_input_max_bitrate = 96;
+	caps->num_cipher_ops = 1;
 
 	/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
 	caps->max_stc = (u64)0xFFFFFF * 256;
@@ -1747,7 +1748,7 @@
 		mpq_dmx_decoder_fullness_abort;
 	mpq_demux->demux.decoder_buffer_status = mpq_dmx_decoder_buffer_status;
 	mpq_demux->demux.reuse_decoder_buffer = mpq_dmx_reuse_decoder_buffer;
-	mpq_demux->demux.set_secure_mode = mpq_dmx_set_secure_mode;
+	mpq_demux->demux.set_cipher_op = mpq_dmx_set_cipher_ops;
 	mpq_demux->demux.oob_command = mpq_dmx_oob_command;
 	mpq_demux->demux.convert_ts = mpq_dmx_convert_tts;
 
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 9837e9f..c2e37a4 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,8 @@
 	}
 
 	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
-		DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
+		DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION |
+		DMX_CAP_SECURED_INPUT_PLAYBACK;
 	caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
 	caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
 	caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -85,6 +86,7 @@
 	caps->max_bitrate = 320;
 	caps->demod_input_max_bitrate = 96;
 	caps->memory_input_max_bitrate = 80;
+	caps->num_cipher_ops = DMX_MAX_CIPHER_OPERATIONS_COUNT;
 
 	/* TSIF reports 7 bytes STC at unit of 27MHz */
 	caps->max_stc = 0x00FFFFFFFFFFFFFF;
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index d673713..50a1ea1 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2385,7 +2385,7 @@
 
 	iris_q_event(radio, IRIS_EVT_NEW_RT_RDS);
 
-	while ((skb->data[len+RDS_OFFSET] != 0x0d) && (len < RX_RT_DATA_LENGTH))
+	while ((skb->data[len+RDS_OFFSET] != 0x0d) && (len < MAX_RT_LENGTH))
 		len++;
 	data = kmalloc(len+RDS_OFFSET, GFP_ATOMIC);
 	if (!data) {
@@ -2397,7 +2397,7 @@
 	data[1] = skb->data[RDS_PTYPE];
 	data[2] = skb->data[RDS_PID_LOWER];
 	data[3] = skb->data[RDS_PID_HIGHER];
-	data[4] = 0;
+	data[4] = skb->data[RT_A_B_FLAG_OFFSET];
 
 	memcpy(data+RDS_OFFSET, &skb->data[RDS_OFFSET], len);
 	data[len+RDS_OFFSET] = 0x00;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 6ea2346..9d0bc61 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -605,11 +605,12 @@
 	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
 
 	ret = __qseecom_check_app_exists(req);
-	if (ret < 0)
+	if (ret < 0) {
+		qsee_disable_clock_vote(data, CLK_SFPB);
 		return ret;
-	else
-		app_id = ret;
+	}
 
+	app_id = ret;
 	if (app_id) {
 		pr_debug("App id %d (%s) already exists\n", app_id,
 			(char *)(req.app_name));
@@ -2008,14 +2009,15 @@
 		pr_err("set_cpus_allowed_ptr failed : ret %d\n",
 				set_cpu_ret);
 		ret = -EFAULT;
-		goto qseecom_load_external_elf_set_cpu_err;
+		goto exit_ion_free;
 	}
+
 	/* Vote for the SFPB clock */
 	ret = qsee_vote_for_clock(data, CLK_SFPB);
 	if (ret) {
 		pr_err("Unable to vote for SFPB clock: ret = %d", ret);
 		ret = -EIO;
-		goto qseecom_load_external_elf_set_cpu_err;
+		goto exit_cpu_restore;
 	}
 	msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len,
 				ION_IOC_CLEAN_INV_CACHES);
@@ -2027,23 +2029,32 @@
 		pr_err("scm_call to load failed : ret %d\n",
 				ret);
 		ret = -EFAULT;
-		goto qseecom_load_external_elf_scm_err;
+		goto exit_disable_clock;
 	}
 
-	if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		pr_err("%s: qseos result incomplete\n", __func__);
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
 		if (ret)
-			pr_err("process_incomplete_cmd failed err: %d\n",
-					ret);
-	} else {
-		if (resp.result != QSEOS_RESULT_SUCCESS) {
-			pr_err("scm_call to load image failed resp.result =%d\n",
-						resp.result);
-			ret = -EFAULT;
-		}
+			pr_err("process_incomplete_cmd failed: err: %d\n", ret);
+		break;
+	case QSEOS_RESULT_FAILURE:
+		pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
+		ret = -EFAULT;
+		break;
+	default:
+		pr_err("scm_call response result %d not supported\n",
+							resp.result);
+		ret = -EFAULT;
+		break;
 	}
 
-qseecom_load_external_elf_scm_err:
+exit_disable_clock:
+	qsee_disable_clock_vote(data, CLK_SFPB);
+exit_cpu_restore:
 	/* Restore the CPU mask */
 	mask = CPU_MASK_ALL;
 	set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
@@ -2052,12 +2063,10 @@
 				set_cpu_ret);
 		ret = -EFAULT;
 	}
-
-qseecom_load_external_elf_set_cpu_err:
+exit_ion_free:
 	/* Deallocate the handle */
 	if (!IS_ERR_OR_NULL(ihandle))
 		ion_free(qseecom.ion_clnt, ihandle);
-	qsee_disable_clock_vote(data, CLK_SFPB);
 	return ret;
 }
 
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d975543..da07947 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1363,7 +1363,7 @@
 	pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
 		mmc_hostname(card->host), __func__);
 
-	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+	err = mmc_switch_ignore_timeout(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_SANITIZE_START, 1,
 					MMC_SANITIZE_REQ_TIMEOUT);
 
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 7a4d19e..e9ac2fc 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -20,7 +20,6 @@
 #include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/test-iosched.h>
-#include <linux/jiffies.h>
 #include "queue.h"
 #include <linux/mmc/mmc.h>
 
@@ -2787,7 +2786,7 @@
 		if (ret)
 			break;
 
-		mtime = jiffies_to_msecs(mbtd->test_info.test_duration);
+		mtime = ktime_to_ms(mbtd->test_info.test_duration);
 
 		test_pr_info("%s: time is %lu msec, size is %u.%u MiB",
 			__func__, mtime,
@@ -2946,7 +2945,7 @@
 		if (ret)
 			break;
 
-		mtime = jiffies_to_msecs(mbtd->test_info.test_duration);
+		mtime = ktime_to_ms(mbtd->test_info.test_duration);
 		byte_count = mbtd->test_info.test_byte_count;
 
 		test_pr_info("%s: time is %lu msec, size is %lu.%lu MiB",
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 04687fa..064d5ec 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -59,6 +59,9 @@
  */
 #define MMC_BKOPS_MAX_TIMEOUT	(30 * 1000) /* max time to wait in ms */
 
+/* Flushing a large amount of cached data may take a long time. */
+#define MMC_FLUSH_REQ_TIMEOUT_MS 30000 /* msec */
+
 static struct workqueue_struct *workqueue;
 
 /*
@@ -785,21 +788,13 @@
 		cmd = mrq->cmd;
 
 		/*
-		 * If host has timed out waiting for the blocking BKOPs
-		 * to complete, card might be still in programming state
-		 * so let's try to bring the card out of programming state.
+		 * If host has timed out waiting for the commands which can be
+		 * HPIed then let the caller handle the timeout error as it may
+		 * want to send the HPI command to bring the card out of
+		 * programming state.
 		 */
-		if (cmd->bkops_busy && cmd->error == -ETIMEDOUT) {
-			if (!mmc_interrupt_hpi(host->card)) {
-				pr_warning("%s: %s: Interrupted blocking bkops\n",
-					   mmc_hostname(host), __func__);
-				cmd->error = 0;
-				break;
-			} else {
-				pr_err("%s: %s: Failed to interrupt blocking bkops\n",
-				       mmc_hostname(host), __func__);
-			}
-		}
+		if (cmd->ignore_timeout && cmd->error == -ETIMEDOUT)
+			break;
 
 		if (!cmd->error || !cmd->retries ||
 		    mmc_card_removed(host->card))
@@ -1064,8 +1059,6 @@
 	}
 
 	err = mmc_send_hpi_cmd(card, &status);
-	if (err)
-		goto out;
 
 	prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
 	do {
@@ -2594,7 +2587,7 @@
 	if (mmc_card_sdio(card))
 		return 0;
 
-	if (mmc_card_mmc(card)) {
+	if (mmc_card_mmc(card) && (card->host->caps & MMC_CAP_HW_RESET)) {
 		rst_n_function = card->ext_csd.rst_n_function;
 		if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) !=
 		    EXT_CSD_RST_N_ENABLED)
@@ -2611,9 +2604,6 @@
 	if (!host->bus_ops->power_restore)
 		return -EOPNOTSUPP;
 
-	if (!(host->caps & MMC_CAP_HW_RESET))
-		return -EOPNOTSUPP;
-
 	if (!card)
 		return -EINVAL;
 
@@ -2623,10 +2613,10 @@
 	mmc_host_clk_hold(host);
 	mmc_set_clock(host, host->f_init);
 
-	if (mmc_card_sd(card))
-		mmc_power_cycle(host);
-	else if (host->ops->hw_reset)
+	if (mmc_card_mmc(card) && host->ops->hw_reset)
 		host->ops->hw_reset(host);
+	else
+		mmc_power_cycle(host);
 
 	/* If the reset has happened, then a status command will fail */
 	if (check) {
@@ -3336,7 +3326,7 @@
 int mmc_flush_cache(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	int err = 0;
+	int err = 0, rc;
 
 	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
 		return err;
@@ -3344,11 +3334,20 @@
 	if (mmc_card_mmc(card) &&
 			(card->ext_csd.cache_size > 0) &&
 			(card->ext_csd.cache_ctrl & 1)) {
-		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				EXT_CSD_FLUSH_CACHE, 1, 0);
-		if (err)
+		err = mmc_switch_ignore_timeout(card, EXT_CSD_CMD_SET_NORMAL,
+						EXT_CSD_FLUSH_CACHE, 1,
+						MMC_FLUSH_REQ_TIMEOUT_MS);
+		if (err == -ETIMEDOUT) {
+			pr_debug("%s: cache flush timeout\n",
+					mmc_hostname(card->host));
+			rc = mmc_interrupt_hpi(card);
+			if (rc)
+				pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
+						mmc_hostname(host), rc);
+		} else if (err) {
 			pr_err("%s: cache flush error %d\n",
 					mmc_hostname(card->host), err);
+		}
 	}
 
 	return err;
@@ -3364,8 +3363,8 @@
 int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
 {
 	struct mmc_card *card = host->card;
-	unsigned int timeout;
-	int err = 0;
+	unsigned int timeout = card->ext_csd.generic_cmd6_time;
+	int err = 0, rc;
 
 	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
 			mmc_card_is_removable(host))
@@ -3376,16 +3375,28 @@
 		enable = !!enable;
 
 		if (card->ext_csd.cache_ctrl ^ enable) {
-			timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
-			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			if (!enable)
+				timeout = MMC_FLUSH_REQ_TIMEOUT_MS;
+
+			err = mmc_switch_ignore_timeout(card,
+					EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_CACHE_CTRL, enable, timeout);
-			if (err)
+
+			if (err == -ETIMEDOUT && !enable) {
+				pr_debug("%s:cache disable operation timeout\n",
+						mmc_hostname(card->host));
+				rc = mmc_interrupt_hpi(card);
+				if (rc)
+					pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
+							mmc_hostname(host), rc);
+			} else if (err) {
 				pr_err("%s: cache %s error %d\n",
 						mmc_hostname(card->host),
 						enable ? "on" : "off",
 						err);
-			else
+			} else {
 				card->ext_csd.cache_ctrl = enable;
+			}
 		}
 	}
 
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 8087ea6..164c418 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -378,13 +378,13 @@
  *	@timeout_ms: timeout (ms) for operation performed by register write,
  *                   timeout of zero implies maximum possible timeout
  *	@use_busy_signal: use the busy signal as response type
- *	@bkops_busy: set this to indicate that we are starting blocking bkops
+ *	@ignore_timeout: set this flag only for commands which can be HPIed
  *
  *	Modifies the EXT_CSD register for selected card.
  */
 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		 unsigned int timeout_ms, bool use_busy_signal,
-		 bool bkops_busy)
+		 bool ignore_timeout)
 {
 	int err;
 	struct mmc_command cmd = {0};
@@ -407,7 +407,7 @@
 
 
 	cmd.cmd_timeout_ms = timeout_ms;
-	cmd.bkops_busy = bkops_busy;
+	cmd.ignore_timeout = ignore_timeout;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err)
@@ -458,6 +458,13 @@
 }
 EXPORT_SYMBOL_GPL(mmc_switch);
 
+int mmc_switch_ignore_timeout(struct mmc_card *card, u8 set, u8 index, u8 value,
+		unsigned int timeout_ms)
+{
+	return __mmc_switch(card, set, index, value, timeout_ms, true, true);
+}
+EXPORT_SYMBOL(mmc_switch_ignore_timeout);
+
 int mmc_send_status(struct mmc_card *card, u32 *status)
 {
 	int err;
@@ -608,7 +615,7 @@
 
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
-		pr_warn("%s: error %d interrupting operation. "
+		pr_debug("%s: error %d interrupting operation. "
 			"HPI command response %#x\n", mmc_hostname(card->host),
 			err, cmd.resp[0]);
 		return err;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 476e75c..b386318 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4319,56 +4319,6 @@
 	return rc;
 }
 
-/*
- * Work around of the unavailability of a power_reset functionality in SD cards
- * by turning the OFF & back ON the regulators supplying the SD card.
- */
-void msmsdcc_hw_reset(struct mmc_host *mmc)
-{
-	struct mmc_card *card = mmc->card;
-	struct msmsdcc_host *host = mmc_priv(mmc);
-	int rc;
-
-	/* Write-protection bits would be lost on a hardware reset in emmc */
-	if (!card || !mmc_card_sd(card))
-		return;
-
-	pr_debug("%s: Starting h/w reset\n", mmc_hostname(host->mmc));
-
-	if (host->plat->translate_vdd || host->plat->vreg_data) {
-
-		/* Disable the regulators */
-		if (host->plat->translate_vdd)
-			rc = host->plat->translate_vdd(mmc_dev(mmc), 0);
-		else if (host->plat->vreg_data)
-			rc = msmsdcc_setup_vreg(host, false, false);
-
-		if (rc) {
-			pr_err("%s: Failed to disable voltage regulator\n",
-				mmc_hostname(host->mmc));
-			BUG_ON(rc);
-		}
-
-		/* 10ms delay for supply to reach the desired voltage level */
-		usleep_range(10000, 12000);
-
-		/* Enable the regulators */
-		if (host->plat->translate_vdd)
-			rc = host->plat->translate_vdd(mmc_dev(mmc), 1);
-		else if (host->plat->vreg_data)
-			rc = msmsdcc_setup_vreg(host, true, false);
-
-		if (rc) {
-			pr_err("%s: Failed to enable voltage regulator\n",
-				mmc_hostname(host->mmc));
-			BUG_ON(rc);
-		}
-
-		/* 10ms delay for supply to reach the desired voltage level */
-		usleep_range(10000, 12000);
-	}
-}
-
 /**
  *	msmsdcc_stop_request - stops ongoing request
  *	@mmc: MMC host, running the request
@@ -4476,7 +4426,6 @@
 	.enable_sdio_irq = msmsdcc_enable_sdio_irq,
 	.start_signal_voltage_switch = msmsdcc_switch_io_voltage,
 	.execute_tuning = msmsdcc_execute_tuning,
-	.hw_reset = msmsdcc_hw_reset,
 	.stop_request = msmsdcc_stop_request,
 	.get_xfer_remain = msmsdcc_get_xfer_remain,
 	.notify_load = msmsdcc_notify_load,
@@ -5364,7 +5313,7 @@
 	mrq = host->curr.mrq;
 
 	if (mrq && mrq->cmd) {
-		if (!mrq->cmd->bkops_busy) {
+		if (!mrq->cmd->ignore_timeout) {
 			pr_info("%s: CMD%d: Request timeout\n",
 				mmc_hostname(host->mmc), mrq->cmd->opcode);
 			msmsdcc_dump_sdcc_state(host);
@@ -6161,7 +6110,6 @@
 	mmc->caps |= plat->mmc_bus_width;
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 	mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
-	mmc->caps |= MMC_CAP_HW_RESET;
 	/*
 	 * If we send the CMD23 before multi block write/read command
 	 * then we need not to send CMD12 at the end of the transfer.
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4ff8fea..01c75e5 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -264,6 +264,7 @@
 	u32 curr_io_level;
 	struct completion pwr_irq_completion;
 	struct sdhci_msm_bus_vote msm_bus_vote;
+	struct device_attribute	polling;
 	u32 clk_rate; /* Keeps track of current clock rate that is set */
 };
 
@@ -1838,6 +1839,42 @@
 	else
 		return 0;
 }
+
+static ssize_t
+show_polling(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	int poll;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	poll = !!(host->mmc->caps & MMC_CAP_NEEDS_POLL);
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", poll);
+}
+
+static ssize_t
+store_polling(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	int value;
+	unsigned long flags;
+
+	if (!kstrtou32(buf, 0, &value)) {
+		spin_lock_irqsave(&host->lock, flags);
+		if (value) {
+			host->mmc->caps |= MMC_CAP_NEEDS_POLL;
+			mmc_detect_change(host->mmc, 0);
+		} else {
+			host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
+		}
+		spin_unlock_irqrestore(&host->lock, flags);
+	}
+	return count;
+}
+
 static ssize_t
 show_sdhci_max_bus_bw(struct device *dev, struct device_attribute *attr,
 			char *buf)
@@ -2410,7 +2447,6 @@
 					MMC_CAP_SET_XPC_300|
 					MMC_CAP_SET_XPC_330;
 
-	msm_host->mmc->caps |= MMC_CAP_HW_RESET;
 	msm_host->mmc->caps2 |= msm_host->pdata->caps2;
 	msm_host->mmc->caps2 |= MMC_CAP2_CORE_RUNTIME_PM;
 	msm_host->mmc->caps2 |= MMC_CAP2_PACKED_WR;
@@ -2464,6 +2500,16 @@
 	if (ret)
 		goto remove_host;
 
+	if (!gpio_is_valid(msm_host->pdata->status_gpio)) {
+		msm_host->polling.show = show_polling;
+		msm_host->polling.store = store_polling;
+		sysfs_attr_init(&msm_host->polling.attr);
+		msm_host->polling.attr.name = "polling";
+		msm_host->polling.attr.mode = S_IRUGO | S_IWUSR;
+		ret = device_create_file(&pdev->dev, &msm_host->polling);
+		if (ret)
+			goto remove_max_bus_bw_file;
+	}
 	ret = pm_runtime_set_active(&pdev->dev);
 	if (ret)
 		pr_err("%s: %s: pm_runtime_set_active failed: err: %d\n",
@@ -2474,6 +2520,8 @@
 	/* Successful initialization */
 	goto out;
 
+remove_max_bus_bw_file:
+	device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
 remove_host:
 	dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 	sdhci_remove_host(host, dead);
@@ -2512,6 +2560,8 @@
 			0xffffffff);
 
 	pr_debug("%s: %s\n", dev_name(&pdev->dev), __func__);
+	if (!gpio_is_valid(msm_host->pdata->status_gpio))
+		device_remove_file(&pdev->dev, &msm_host->polling);
 	device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
 	sdhci_remove_host(host, dead);
 	pm_runtime_disable(&pdev->dev);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ce1c536..2aff67d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2312,9 +2312,11 @@
 	spin_lock_irqsave(&host->lock, flags);
 
 	if (host->mrq) {
-		pr_err("%s: Timeout waiting for hardware "
-			"interrupt.\n", mmc_hostname(host->mmc));
-		sdhci_dumpregs(host);
+		if (!host->mrq->cmd->ignore_timeout) {
+			pr_err("%s: Timeout waiting for hardware interrupt.\n",
+			       mmc_hostname(host->mmc));
+			sdhci_dumpregs(host);
+		}
 
 		if (host->data) {
 			pr_info("%s: bytes to transfer: %d transferred: %d\n",
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index efa09f6..16012bd 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -694,7 +694,7 @@
 	dma_addr_t dma_addr_param_info = 0;
 	struct onfi_param_page *onfi_param_page_ptr;
 	struct msm_nand_flash_onfi_data data;
-	uint32_t onfi_signature;
+	uint32_t onfi_signature = 0;
 
 	/* SPS command/data descriptors */
 	uint32_t total_cnt = 13;
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 06c304a..180b856 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -20,6 +20,7 @@
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinconf-generic.h>
+#include <linux/of.h>
 #include "core.h"
 #include "pinconf.h"
 
@@ -36,11 +37,15 @@
 struct pin_config_item conf_items[] = {
 	PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
 	PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
+	PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL),
 	PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
 	PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL),
+	PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
+				"input bias pull to pin specific state", NULL),
 	PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
 	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
 	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
+	PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA"),
 	PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL),
 	PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
 	PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
@@ -121,3 +126,103 @@
 }
 
 #endif
+
+#ifdef CONFIG_OF
+struct pinconf_generic_dt_params {
+	const char * const property;
+	enum pin_config_param param;
+	u32 default_value;
+};
+
+static struct pinconf_generic_dt_params dt_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
+	{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+	{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
+	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
+	{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
+	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+	{ "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
+	{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
+	{ "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
+	{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
+	{ "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
+	{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
+	{ "output-low", PIN_CONFIG_OUTPUT, 0, },
+	{ "output-high", PIN_CONFIG_OUTPUT, 1, },
+};
+
+/**
+ * pinconf_generic_parse_dt_config()
+ * parse the config properties into generic pinconfig values.
+ * @np: node containing the pinconfig properties
+ * @configs: array with nconfigs entries containing the generic pinconf values
+ * @nconfigs: umber of configurations
+ */
+int pinconf_generic_parse_dt_config(struct device_node *np,
+				    unsigned long **configs,
+				    unsigned int *nconfigs)
+{
+	unsigned long *cfg;
+	unsigned int ncfg = 0;
+	int ret;
+	int i;
+	u32 val;
+
+	if (!np)
+		return -EINVAL;
+
+	/* allocate a temporary array big enough to hold one of each option */
+	cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL);
+	if (!cfg)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
+		struct pinconf_generic_dt_params *par = &dt_params[i];
+		ret = of_property_read_u32(np, par->property, &val);
+
+		/* property not found */
+		if (ret == -EINVAL)
+			continue;
+
+		/* use default value, when no value is specified */
+		if (ret)
+			val = par->default_value;
+
+		pr_debug("found %s with value %u\n", par->property, val);
+		cfg[ncfg] = pinconf_to_config_packed(par->param, val);
+		ncfg++;
+	}
+
+	ret = 0;
+
+	/* no configs found at all */
+	if (ncfg == 0) {
+		*configs = NULL;
+		*nconfigs = 0;
+		goto out;
+	}
+
+	/*
+	 * Now limit the number of configs to the real number of
+	 * found properties.
+	 */
+	*configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL);
+	if (!*configs) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(*configs, cfg, ncfg * sizeof(unsigned long));
+	*nconfigs = ncfg;
+
+out:
+	kfree(cfg);
+	return ret;
+}
+#endif
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index bfda73d..bf21525 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -115,3 +115,9 @@
 }
 
 #endif
+
+#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF)
+int pinconf_generic_parse_dt_config(struct device_node *np,
+				    unsigned long **configs,
+				    unsigned int *nconfigs);
+#endif
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 4df511b..14d5b6a 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -135,6 +135,7 @@
 struct qpnp_bms_chip {
 	struct device			*dev;
 	struct power_supply		bms_psy;
+	bool				bms_psy_registered;
 	struct power_supply		*batt_psy;
 	struct spmi_device		*spmi;
 	u16				base;
@@ -1483,7 +1484,7 @@
 
 	if (params->rbatt_mohm != chip->rbatt_mohm) {
 		chip->rbatt_mohm = params->rbatt_mohm;
-		if (chip->bms_psy.name != NULL)
+		if (chip->bms_psy_registered)
 			power_supply_changed(&chip->bms_psy);
 	}
 
@@ -2288,8 +2289,7 @@
 	}
 	mutex_unlock(&chip->last_soc_mutex);
 
-	if (new_calculated_soc != previous_soc
-			&& chip->bms_psy.name != NULL) {
+	if (new_calculated_soc != previous_soc && chip->bms_psy_registered) {
 		power_supply_changed(&chip->bms_psy);
 		pr_debug("power supply changed\n");
 	} else {
@@ -2323,7 +2323,7 @@
 	voltage_based_soc = clamp(voltage_based_soc, 0, 100);
 
 	if (chip->prev_voltage_based_soc != voltage_based_soc
-				&& chip->bms_psy.name != NULL) {
+				&& chip->bms_psy_registered) {
 		power_supply_changed(&chip->bms_psy);
 		pr_debug("power supply changed\n");
 	}
@@ -2530,7 +2530,7 @@
 	} else {
 		pr_debug("unknown voltage notification state: %d\n", state);
 	}
-	if (chip->bms_psy.name != NULL)
+	if (chip->bms_psy_registered)
 		power_supply_changed(&chip->bms_psy);
 }
 
@@ -3419,7 +3419,7 @@
 	chip->first_time_calc_uuc = 1;
 }
 
-#define SPMI_SETUP_IRQ(irq_name)					\
+#define SPMI_FIND_IRQ(chip, irq_name)					\
 do {									\
 	chip->irq_name##_irq.irq = spmi_get_irq_byname(chip->spmi,	\
 					resource, #irq_name);		\
@@ -3427,6 +3427,18 @@
 		pr_err("Unable to get " #irq_name " irq\n");		\
 		return -ENXIO;						\
 	}								\
+} while (0)
+
+static int bms_find_irqs(struct qpnp_bms_chip *chip,
+			struct spmi_resource *resource)
+{
+	SPMI_FIND_IRQ(chip, sw_cc_thr);
+	SPMI_FIND_IRQ(chip, ocv_thr);
+	return 0;
+}
+
+#define SPMI_REQUEST_IRQ(chip, rc, irq_name)				\
+do {									\
 	rc = devm_request_irq(chip->dev, chip->irq_name##_irq.irq,	\
 			bms_##irq_name##_irq_handler,			\
 			IRQF_TRIGGER_RISING, #irq_name, chip);		\
@@ -3436,14 +3448,13 @@
 	}								\
 } while (0)
 
-static int bms_setup_irqs(struct qpnp_bms_chip *chip,
-			struct spmi_resource *resource)
+static int bms_request_irqs(struct qpnp_bms_chip *chip)
 {
 	int rc;
 
-	SPMI_SETUP_IRQ(sw_cc_thr);
+	SPMI_REQUEST_IRQ(chip, rc, sw_cc_thr);
 	enable_irq_wake(chip->sw_cc_thr_irq.irq);
-	SPMI_SETUP_IRQ(ocv_thr);
+	SPMI_REQUEST_IRQ(chip, rc, ocv_thr);
 	enable_irq_wake(chip->ocv_thr_irq.irq);
 	return 0;
 }
@@ -3495,9 +3506,9 @@
 
 		if (type == BMS_BMS_TYPE && subtype == BMS_BMS1_SUBTYPE) {
 			chip->base = resource->start;
-			rc = bms_setup_irqs(chip, spmi_resource);
+			rc = bms_find_irqs(chip, spmi_resource);
 			if (rc) {
-				pr_err("Could not register irqs\n");
+				pr_err("Could not find irqs\n");
 				return rc;
 			}
 		} else if (type == BMS_IADC_TYPE
@@ -3824,6 +3835,7 @@
 		goto unregister_dc;
 	}
 
+	chip->bms_psy_registered = true;
 	vbatt = 0;
 	rc = get_battery_voltage(&vbatt);
 	if (rc) {
@@ -3832,12 +3844,19 @@
 		goto unregister_dc;
 	}
 
+	rc = bms_request_irqs(chip);
+	if (rc) {
+		pr_err("error requesting bms irqs, rc = %d\n", rc);
+		goto unregister_dc;
+	}
+
 	pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u warm_reset = %d\n",
 			get_prop_bms_capacity(chip), vbatt, chip->last_ocv_uv,
 			chip->r_sense_uohm, warm_reset);
 	return 0;
 
 unregister_dc:
+	chip->bms_psy_registered = false;
 	power_supply_unregister(&chip->bms_psy);
 error_setup:
 	dev_set_drvdata(&spmi->dev, NULL);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 983a901..2a007ca 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -98,6 +98,7 @@
 #define BOOST_VSET				0x41
 #define BOOST_ENABLE_CONTROL			0x46
 #define COMP_OVR1				0xEA
+#define BAT_IF_BTC_CTRL				0x49
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
 
@@ -222,6 +223,7 @@
  * @dc_present:			present status of dc
  * @batt_present:		present status of battery
  * @use_default_batt_values:	flag to report default battery properties
+ * @btc_disabled		Flag to disable btc (disables hot and cold irqs)
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
  * @max_bat_chg_current:	maximum battery charge current in mA
@@ -234,6 +236,8 @@
  * @safe_current:		battery safety current setting
  * @maxinput_usb_ma:		Maximum Input current USB
  * @maxinput_dc_ma:		Maximum Input current DC
+ * @hot_batt_p			Hot battery threshold setting
+ * @cold_batt_p			Cold battery threshold setting
  * @warm_bat_decidegc		Warm battery temperature in degree Celsius
  * @cool_bat_decidegc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
@@ -276,6 +280,7 @@
 	bool				dc_present;
 	bool				batt_present;
 	bool				charging_disabled;
+	bool				btc_disabled;
 	bool				use_default_batt_values;
 	bool				duty_cycle_100p;
 	unsigned int			bpd_detection;
@@ -291,8 +296,12 @@
 	unsigned int			cool_bat_mv;
 	unsigned int			resume_delta_mv;
 	int				term_current;
+	int				soc_resume_limit;
+	bool				resuming_charging;
 	unsigned int			maxinput_usb_ma;
 	unsigned int			maxinput_dc_ma;
+	unsigned int			hot_batt_p;
+	unsigned int			cold_batt_p;
 	unsigned int			warm_bat_decidegc;
 	unsigned int			cool_bat_decidegc;
 	unsigned int			safe_current;
@@ -334,7 +343,21 @@
 	[BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
 };
 
-static inline int
+enum btc_type {
+	HOT_THD_25_PCT = 25,
+	HOT_THD_35_PCT = 35,
+	COLD_THD_70_PCT = 70,
+	COLD_THD_80_PCT = 80,
+};
+
+static u8 btc_value[] = {
+	[HOT_THD_25_PCT] = 0x0,
+	[HOT_THD_35_PCT] = BIT(0),
+	[COLD_THD_70_PCT] = 0x0,
+	[COLD_THD_80_PCT] = BIT(1),
+};
+
+	static inline int
 get_bpd(const char *name)
 {
 	int i = 0;
@@ -736,6 +759,23 @@
 }
 
 static void
+qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
+{
+	if (chip->bat_is_cool)
+		qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
+			- chip->resume_delta_mv);
+	else if (chip->bat_is_warm)
+		qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
+			- chip->resume_delta_mv);
+	else if (chip->resuming_charging)
+		qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+			+ chip->resume_delta_mv);
+	else
+		qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+			- chip->resume_delta_mv);
+}
+
+static void
 qpnp_arb_stop_work(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
@@ -934,6 +974,10 @@
 	power_supply_changed(chip->usb_psy);
 	if (chip->dc_chgpth_base)
 		power_supply_changed(&chip->dc_psy);
+	if (chip->resuming_charging) {
+		chip->resuming_charging = false;
+		qpnp_chg_set_appropriate_vbatdet(chip);
+	}
 	qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
 
 	return IRQ_HANDLED;
@@ -1274,6 +1318,16 @@
 	if (chip->bms_psy) {
 		chip->bms_psy->get_property(chip->bms_psy,
 			  POWER_SUPPLY_PROP_CAPACITY, &ret);
+		if (get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL
+				&& !chip->resuming_charging
+				&& !chip->charging_disabled
+				&& chip->soc_resume_limit
+				&& ret.intval <= chip->soc_resume_limit) {
+			pr_debug("resuming charging at %d%% soc\n", ret.intval);
+			chip->resuming_charging = true;
+			qpnp_chg_set_appropriate_vbatdet(chip);
+			qpnp_chg_charge_en(chip, !chip->charging_disabled);
+		}
 		if (ret.intval == 0) {
 			if (!qpnp_chg_is_usb_chg_plugged_in(chip)
 				&& !qpnp_chg_is_usb_chg_plugged_in(chip))
@@ -1416,7 +1470,39 @@
 	return 0;
 }
 
-#define QPNP_CHG_VINMIN_MIN_MV		3400
+#define BTC_CONFIG_ENABLED	BIT(7)
+#define BTC_COLD		BIT(1)
+#define BTC_HOT			BIT(0)
+static int
+qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
+{
+	u8 btc_cfg = 0, mask = 0;
+
+	/* Do nothing if battery peripheral not present */
+	if (!chip->bat_if_base)
+		return 0;
+
+	if ((chip->hot_batt_p == HOT_THD_25_PCT)
+			|| (chip->hot_batt_p == HOT_THD_35_PCT)) {
+		btc_cfg |= btc_value[chip->hot_batt_p];
+		mask |= BTC_HOT;
+	}
+
+	if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
+			(chip->cold_batt_p == COLD_THD_80_PCT)) {
+		btc_cfg |= btc_value[chip->cold_batt_p];
+		mask |= BTC_COLD;
+	}
+
+	if (chip->btc_disabled)
+		mask |= BTC_CONFIG_ENABLED;
+
+	return qpnp_chg_masked_write(chip,
+			chip->bat_if_base + BAT_IF_BTC_CTRL,
+			mask, btc_cfg, 1);
+}
+
+#define QPNP_CHG_VINMIN_MIN_MV		4200
 #define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
 #define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
 #define QPNP_CHG_VINMIN_MAX_MV		9600
@@ -1621,20 +1707,6 @@
 }
 
 static void
-qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
-{
-	if (chip->bat_is_cool)
-		qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
-			- chip->resume_delta_mv);
-	else if (chip->bat_is_warm)
-		qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
-			- chip->resume_delta_mv);
-	else
-		qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
-			- chip->resume_delta_mv);
-}
-
-static void
 qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
 {
 	unsigned int chg_current = chip->max_bat_chg_current;
@@ -2076,7 +2148,16 @@
 		chip->bat_is_cool = bat_cool;
 		chip->bat_is_warm = bat_warm;
 
-		/* set appropriate voltages and currents */
+		if (bat_cool || bat_warm)
+			chip->resuming_charging = false;
+
+		/**
+		 * set appropriate voltages and currents.
+		 *
+		 * Note that when the battery is hot or cold, the charger
+		 * driver will not resume with SoC. Only vbatdet is used to
+		 * determine resume of charging.
+		 */
 		qpnp_chg_set_appropriate_vddmax(chip);
 		qpnp_chg_set_appropriate_battery_current(chip);
 		qpnp_chg_set_appropriate_vbatdet(chip);
@@ -2637,6 +2718,10 @@
 	OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
 	OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
 	OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
+	OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
+	OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
+	OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
+
 	if (rc)
 		return rc;
 
@@ -2669,6 +2754,10 @@
 			return rc;
 	}
 
+	/* Get the btc-disabled property */
+	chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,btc-disabled");
+
 	/* Get the charging-disabled property */
 	chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,charging-disabled");
@@ -2992,6 +3081,11 @@
 			}
 		}
 	}
+	rc = qpnp_chg_bat_if_configure_btc(chip);
+	if (rc) {
+		pr_err("failed to configure btc %d\n", rc);
+		goto unregister_batt;
+	}
 
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
index e0bffb9..bfbae78 100644
--- a/drivers/rtc/qpnp-rtc.c
+++ b/drivers/rtc/qpnp-rtc.c
@@ -45,6 +45,11 @@
 #define TO_SECS(arr)		(arr[0] | (arr[1] << 8) | (arr[2] << 16) | \
 							(arr[3] << 24))
 
+/* Module parameter to control power-on-alarm */
+static bool poweron_alarm;
+module_param(poweron_alarm, bool, 0644);
+MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm");
+
 /* rtc driver internal structure */
 struct qpnp_rtc {
 	u8  rtc_ctrl_reg;
@@ -586,7 +591,7 @@
 	struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
 	bool rtc_alarm_powerup = rtc_dd->rtc_alarm_powerup;
 
-	if (!rtc_alarm_powerup) {
+	if (!rtc_alarm_powerup && !poweron_alarm) {
 		spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
 		dev_dbg(&spmi->dev, "Disabling alarm interrupts\n");
 
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c
index 03c58a4..dbab808 100644
--- a/drivers/scsi/ufs/ufs_test.c
+++ b/drivers/scsi/ufs/ufs_test.c
@@ -18,13 +18,27 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
 #include <../sd.h>
+#include <linux/delay.h>
 
 #define MODULE_NAME "ufs_test"
 
-#define TEST_MAX_BIOS_PER_REQ		120
+#define TEST_MAX_BIOS_PER_REQ		16
 #define LARGE_PRIME_1	1103515367
 #define LARGE_PRIME_2	35757
-#define DEFAULT_NUM_OF_BIOS	2
+#define DEFAULT_NUM_OF_BIOS		2
+
+/* the amount of requests that will be inserted */
+#define LONG_SEQ_TEST_NUM_REQS  256
+/* request queue limitation is 128 requests, and we leave 10 spare requests */
+#define QUEUE_MAX_REQUESTS 118
+#define MB_MSEC_RATIO_APPROXIMATION ((1024 * 1024) / 1000)
+/* actual number of MiB in test multiplied by 10, for single digit precision*/
+#define BYTE_TO_MB_x_10(x) ((x * 10) / (1024 * 1024))
+/* extract integer value */
+#define LONG_TEST_SIZE_INTEGER(x) (BYTE_TO_MB_x_10(x) / 10)
+/* and calculate the MiB value fraction */
+#define LONG_TEST_SIZE_FRACTION(x) (BYTE_TO_MB_x_10(x) - \
+		(LONG_TEST_SIZE_INTEGER(x) * 10))
 
 #define test_pr_debug(fmt, args...) pr_debug("%s: "fmt"\n", MODULE_NAME, args)
 #define test_pr_info(fmt, args...) pr_info("%s: "fmt"\n", MODULE_NAME, args)
@@ -32,11 +46,16 @@
 
 enum ufs_test_testcases {
 	UFS_TEST_WRITE_READ_TEST,
+
+	TEST_LONG_SEQUENTIAL_READ,
+	TEST_LONG_SEQUENTIAL_WRITE,
 };
 
 struct ufs_test_debug {
 	struct dentry *write_read_test; /* basic test */
 	struct dentry *random_test_seed; /* parameters in utils */
+	struct dentry *long_sequential_read_test;
+	struct dentry *long_sequential_write_test;
 };
 
 struct ufs_test_data {
@@ -60,6 +79,8 @@
 	 * disabled and 2 BIOs are written.
 	 */
 	unsigned int random_test_seed;
+	/* A counter for the number of test requests completed */
+	unsigned int completed_req_count;
 };
 
 static struct ufs_test_data *utd;
@@ -77,6 +98,12 @@
 	case UFS_TEST_WRITE_READ_TEST:
 		return "UFS write read test";
 		break;
+	case TEST_LONG_SEQUENTIAL_READ:
+		return "UFS long sequential read test";
+		break;
+	case TEST_LONG_SEQUENTIAL_WRITE:
+		return "UFS long sequential write test";
+		break;
 	default:
 		return "Unknown test";
 	}
@@ -166,8 +193,9 @@
 		num_bios = DEFAULT_NUM_OF_BIOS;
 
 	/* Adding a write request */
-	test_pr_info("%s: Adding a write requests to Q, first req_id=%d",
-			__func__, td->wr_rd_next_req_id);
+	test_pr_info(
+		"%s: Adding a write request with %d bios to Q, req_id=%d"
+			, __func__, num_bios, td->wr_rd_next_req_id);
 
 	utd->write_completed = false;
 	ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec,
@@ -265,21 +293,290 @@
 		.read = ufs_test_write_read_test_read_cb,
 };
 
+static void long_seq_test_free_end_io_fn(struct request *rq, int err)
+{
+	struct test_request *test_rq;
+	struct test_data *ptd = test_get_test_data();
+
+	if (rq)
+		test_rq = (struct test_request *)rq->elv.priv[0];
+	else {
+		test_pr_err("%s: error: NULL request", __func__);
+		return;
+	}
+
+	BUG_ON(!test_rq);
+
+	spin_lock_irq(&ptd->lock);
+	ptd->dispatched_count--;
+	list_del_init(&test_rq->queuelist);
+	__blk_put_request(ptd->req_q, test_rq->rq);
+	spin_unlock_irq(&ptd->lock);
+
+	kfree(test_rq->bios_buffer);
+	kfree(test_rq);
+	utd->completed_req_count++;
+
+	test_pr_err("%s: request %d completed, err=%d",
+	       __func__, test_rq->req_id, err);
+
+	check_test_completion();
+
+}
+
+static int run_long_seq_test(struct test_data *td)
+{
+	int ret = 0;
+	int direction;
+	static unsigned int inserted_requests;
+
+	BUG_ON(!td);
+	td->test_count = 0;
+	utd->completed_req_count = 0;
+	inserted_requests = 0;
+
+	if (td->test_info.testcase == TEST_LONG_SEQUENTIAL_READ)
+		direction = READ;
+	else
+		direction = WRITE;
+
+	test_pr_info("%s: Adding %d requests, first req_id=%d",
+		     __func__, LONG_SEQ_TEST_NUM_REQS,
+		     td->wr_rd_next_req_id);
+
+	do {
+		/*
+		* since our requests come from a pool containing 128
+		* requests, we don't want to exhaust this quantity,
+		* therefore we add up to QUEUE_MAX_REQUESTS (which
+		* includes a safety margin) and then call the mmc layer
+		* to fetch them
+		*/
+		if (td->test_count >= QUEUE_MAX_REQUESTS) {
+			blk_run_queue(td->req_q);
+			continue;
+		}
+
+		ret = test_iosched_add_wr_rd_test_req(0, direction,
+			td->start_sector, TEST_MAX_BIOS_PER_REQ,
+			TEST_PATTERN_5A,
+			long_seq_test_free_end_io_fn);
+		if (ret) {
+			test_pr_err("%s: failed to create request" , __func__);
+			break;
+		}
+		inserted_requests++;
+		td->test_info.test_byte_count +=
+			(TEST_MAX_BIOS_PER_REQ * sizeof(unsigned int) *
+			BIO_U32_SIZE);
+
+	} while (inserted_requests < LONG_SEQ_TEST_NUM_REQS);
+
+	/* in this case the queue will not run in the above loop */
+	if (LONG_SEQ_TEST_NUM_REQS < QUEUE_MAX_REQUESTS)
+		blk_run_queue(td->req_q);
+
+	return ret;
+}
+
+
+void long_seq_test_calc_throughput(unsigned long mtime,
+				   unsigned long byte_count)
+{
+	unsigned long fraction, integer;
+
+	test_pr_info("%s: time is %lu msec, size is %lu.%lu MiB",
+			__func__, mtime, LONG_TEST_SIZE_INTEGER(byte_count),
+				LONG_TEST_SIZE_FRACTION(byte_count));
+
+	/* we first multiply in order not to lose precision */
+	mtime *= MB_MSEC_RATIO_APPROXIMATION;
+	/* divide values to get a MiB/sec integer value with one
+	   digit of precision
+	   */
+	fraction = integer = (byte_count * 10) / mtime;
+	integer /= 10;
+	/* and calculate the MiB value fraction */
+	fraction -= integer * 10;
+
+	test_pr_info("%s: Throughput: %lu.%lu MiB/sec\n",
+		__func__, integer, fraction);
+}
+
+static ssize_t long_sequential_read_test_write(struct file *file,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int ret = 0;
+	int i = 0;
+	int number = -1;
+	unsigned long mtime, byte_count;
+
+	test_pr_info("%s: -- UFS Long Sequential Read TEST --", __func__);
+
+	sscanf(buf, "%d", &number);
+
+	if (number <= 0)
+		number = 1;
+
+	memset(&utd->test_info, 0, sizeof(struct test_info));
+
+	utd->test_info.data = utd;
+	utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+	utd->test_info.run_test_fn = run_long_seq_test;
+	utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+	utd->test_info.testcase = TEST_LONG_SEQUENTIAL_READ;
+
+	for (i = 0 ; i < number ; ++i) {
+		test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+		test_pr_info("%s: ====================", __func__);
+
+		ret = test_iosched_start_test(&utd->test_info);
+		if (ret)
+			break;
+
+		mtime = ktime_to_ms(utd->test_info.test_duration);
+		byte_count = utd->test_info.test_byte_count;
+
+		long_seq_test_calc_throughput(mtime, byte_count);
+
+		/* Allow FS requests to be dispatched */
+		msleep(1000);
+	}
+
+	return count;
+}
+
+static ssize_t long_sequential_read_test_read(struct file *file,
+			       char __user *buffer,
+			       size_t count,
+			       loff_t *offset)
+{
+	memset((void *)buffer, 0, count);
+
+	snprintf(buffer, count,
+		 "\nufs_long_sequential_read_test\n"
+		 "=========\n"
+		 "Description:\n"
+		 "This test runs the following scenarios\n"
+		 "- Long Sequential Read Test: this test measures read "
+		 "throughput at the driver level by sequentially reading many "
+		 "large requests.\n");
+
+	if (message_repeat == 1) {
+		message_repeat = 0;
+		return strnlen(buffer, count);
+	} else
+		return 0;
+}
+
+static bool message_repeat;
+static int test_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	message_repeat = 1;
+	return 0;
+}
+
+const struct file_operations long_sequential_read_test_ops = {
+	.open = test_open,
+	.write = long_sequential_read_test_write,
+	.read = long_sequential_read_test_read,
+};
+
+static ssize_t long_sequential_write_test_write(struct file *file,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int ret = 0;
+	int i = 0;
+	int number = -1;
+	unsigned long mtime, byte_count;
+
+	test_pr_info("%s: -- UFS Long Sequential Write TEST --", __func__);
+
+	sscanf(buf, "%d", &number);
+
+	if (number <= 0)
+		number = 1;
+
+	memset(&utd->test_info, 0, sizeof(struct test_info));
+
+	utd->test_info.data = utd;
+	utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+	utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+	utd->test_info.run_test_fn = run_long_seq_test;
+	utd->test_info.testcase = TEST_LONG_SEQUENTIAL_WRITE;
+
+	for (i = 0 ; i < number ; ++i) {
+		test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+		test_pr_info("%s: ====================", __func__);
+
+		utd->test_info.test_byte_count = 0;
+		ret = test_iosched_start_test(&utd->test_info);
+		if (ret)
+			break;
+
+		mtime = ktime_to_ms(utd->test_info.test_duration);
+		byte_count = utd->test_info.test_byte_count;
+
+		long_seq_test_calc_throughput(mtime, byte_count);
+
+		/* Allow FS requests to be dispatched */
+		msleep(1000);
+	}
+
+	return count;
+}
+
+static ssize_t long_sequential_write_test_read(struct file *file,
+			       char __user *buffer,
+			       size_t count,
+			       loff_t *offset)
+{
+	memset((void *)buffer, 0, count);
+
+	snprintf(buffer, count,
+		 "\nufs_long_sequential_write_test\n"
+		 "=========\n"
+		 "Description:\n"
+		 "This test runs the following scenarios\n"
+		 "- Long Sequential Write Test: this test measures write "
+		 "throughput at the driver level by sequentially writing many "
+		 "large requests\n");
+
+	if (message_repeat == 1) {
+		message_repeat = 0;
+		return strnlen(buffer, count);
+	} else
+		return 0;
+}
+
+const struct file_operations long_sequential_write_test_ops = {
+	.open = test_open,
+	.write = long_sequential_write_test_write,
+	.read = long_sequential_write_test_read,
+};
+
 static void ufs_test_debugfs_cleanup(void)
 {
-	debugfs_remove(utd->debug.write_read_test);
+	debugfs_remove_recursive(test_iosched_get_debugfs_tests_root());
 }
 
 static int ufs_test_debugfs_init(void)
 {
 	struct dentry *utils_root, *tests_root;
+	int ret = 0;
 
 	utils_root = test_iosched_get_debugfs_utils_root();
 	tests_root = test_iosched_get_debugfs_tests_root();
 
 	if (!utils_root || !tests_root) {
 		test_pr_err("%s: Failed to create debugfs root.", __func__);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto exit;
 	}
 
 	utd->debug.random_test_seed = debugfs_create_u32("random_test_seed",
@@ -288,21 +585,49 @@
 	if (!utd->debug.random_test_seed) {
 		test_pr_err("%s: Could not create debugfs random_test_seed.",
 				__func__);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto exit;
 	}
 
-	utd->debug.write_read_test = debugfs_create_file("write_read_test",
+	utd->debug.write_read_test = debugfs_create_file("ufs_write_read_test",
 					S_IRUGO | S_IWUGO, tests_root,
 					NULL, &write_read_test_ops);
 
 	if (!utd->debug.write_read_test) {
-		debugfs_remove(utd->debug.random_test_seed);
-		test_pr_err("%s: Could not create debugfs write_read_test.",
-				__func__);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto exit_err;
 	}
 
-	return 0;
+	utd->debug.long_sequential_read_test = debugfs_create_file(
+					"ufs_long_sequential_read_test",
+					S_IRUGO | S_IWUGO,
+					tests_root,
+					NULL,
+					&long_sequential_read_test_ops);
+
+	if (!utd->debug.long_sequential_read_test) {
+		ret = -ENOMEM;
+		goto exit_err;
+	}
+
+	utd->debug.long_sequential_write_test = debugfs_create_file(
+					"ufs_long_sequential_write_test",
+					S_IRUGO | S_IWUGO,
+					tests_root,
+					NULL,
+					&long_sequential_write_test_ops);
+
+	if (!utd->debug.long_sequential_write_test) {
+		ret = -ENOMEM;
+		goto exit_err;
+	}
+
+	goto exit;
+
+exit_err:
+	debugfs_remove_recursive(tests_root);
+exit:
+	return ret;
 }
 
 static void ufs_test_probe(void)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 48a7645..2230f14 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -802,7 +802,7 @@
 		utrdlp[i].prd_table_offset =
 				cpu_to_le16((prdt_offset >> 2));
 		utrdlp[i].response_upiu_length =
-				cpu_to_le16(ALIGNED_UPIU_SIZE);
+				cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
 
 		hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
 		hba->lrb[i].ucd_cmd_ptr =
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 97d47db..6e7a815 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -30,12 +30,6 @@
 #define MSM_SLIM_NAME	"msm_slim_ctrl"
 #define SLIM_ROOT_FREQ 24576000
 
-#define QC_MFGID_LSB	0x2
-#define QC_MFGID_MSB	0x17
-#define QC_CHIPID_SL	0x10
-#define QC_DEVID_SAT1	0x3
-#define QC_DEVID_SAT2	0x4
-#define QC_DEVID_PGD	0x5
 #define QC_MSM_DEVS	5
 
 /* Manager registers */
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 509c1e8..2f19863 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -306,8 +306,26 @@
 			txn->mc = SLIM_USR_MC_CONNECT_SINK;
 		else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
 			txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
-		if (txn->la == SLIM_LA_MGR)
+		if (txn->la == SLIM_LA_MGR) {
+			if (dev->pgdla == SLIM_LA_MGR) {
+				u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
+						QC_MFGID_LSB};
+				ea[2] = (u8)(dev->pdata.eapc & 0xFF);
+				ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
+				mutex_unlock(&dev->tx_lock);
+				ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
+						&dev->pgdla);
+				pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
+						ret);
+				if (ret) {
+					pr_err("Incorrect SLIM-PGD EAPC:0x%x",
+							dev->pdata.eapc);
+					return ret;
+				}
+				mutex_lock(&dev->tx_lock);
+			}
 			txn->la = dev->pgdla;
+		}
 		wbuf[i++] = txn->la;
 		la = SLIM_LA_MGR;
 		wbuf[i++] = txn->wbuf[0];
@@ -380,6 +398,8 @@
 			dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
 			goto ngd_xfer_err;
 		}
+		/* Add port-base to port number if this is manager side port */
+		puc[1] += dev->port_b;
 	}
 	dev->err = 0;
 	dev->wr_comp = &tx_sent;
@@ -1070,9 +1090,18 @@
 		}
 		rxreg_access = of_property_read_bool(pdev->dev.of_node,
 					"qcom,rxreg-access");
+		of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
+					&dev->pdata.apps_pipes);
+		of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
+					&dev->pdata.eapc);
 	} else {
 		dev->ctrl.nr = pdev->id;
 	}
+	/*
+	 * Keep PGD's logical address as manager's. Query it when first data
+	 * channel request comes in
+	 */
+	dev->pgdla = SLIM_LA_MGR;
 	dev->ctrl.nchans = MSM_SLIM_NCHANS;
 	dev->ctrl.nports = MSM_SLIM_NPORTS;
 	dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index a63ee76..37bc883 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -788,6 +788,10 @@
 	bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
 				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
 
+	/* override apps channel pipes if specified in platform-data or DT */
+	if (dev->pdata.apps_pipes)
+		sec_props.ees[dev->ee].pipe_mask = dev->pdata.apps_pipes;
+
 	/* First 7 bits are for message Qs */
 	for (i = 7; i < 32; i++) {
 		/* Check what pipes are owned by Apps. */
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 896e196..b5c41ed 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -50,6 +50,13 @@
 #define MSM_SLIM_NPORTS			24
 #define MSM_SLIM_NCHANS			32
 
+#define QC_MFGID_LSB	0x2
+#define QC_MFGID_MSB	0x17
+#define QC_CHIPID_SL	0x10
+#define QC_DEVID_SAT1	0x3
+#define QC_DEVID_SAT2	0x4
+#define QC_DEVID_PGD	0x5
+
 #define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
 		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
 
@@ -198,6 +205,11 @@
 	struct work_struct		ssr_up;
 };
 
+struct msm_slim_pdata {
+	u32 apps_pipes;
+	u32 eapc;
+};
+
 struct msm_slim_ctrl {
 	struct slim_controller  ctrl;
 	struct slim_framer	framer;
@@ -240,6 +252,7 @@
 	u32			ver;
 	struct work_struct	slave_notify;
 	struct msm_slim_qmi	qmi;
+	struct msm_slim_pdata	pdata;
 };
 
 struct msm_sat_chan {
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index bcec934..97d412d 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -84,8 +84,6 @@
 
 source "drivers/staging/zcache/Kconfig"
 
-source "drivers/staging/qcache/Kconfig"
-
 source "drivers/staging/zsmalloc/Kconfig"
 
 source "drivers/staging/wlags49_h2/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index c31f2ec..ffe7d44 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -34,7 +34,6 @@
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_ZRAM)		+= zram/
 obj-$(CONFIG_ZCACHE)		+= zcache/
-obj-$(CONFIG_QCACHE)		+= qcache/
 obj-$(CONFIG_ZSMALLOC)		+= zsmalloc/
 obj-$(CONFIG_WLAGS49_H2)	+= wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)	+= wlags49_h25/
diff --git a/drivers/staging/qcache/Kconfig b/drivers/staging/qcache/Kconfig
deleted file mode 100644
index 389341c..0000000
--- a/drivers/staging/qcache/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-config QCACHE
-	tristate "Dynamic compression of clean pagecache pages"
-	depends on CLEANCACHE
-	select LZO_COMPRESS
-	select LZO_DECOMPRESS
-	default n
-	help
-	  Qcache is the backend for fmem
diff --git a/drivers/staging/qcache/Makefile b/drivers/staging/qcache/Makefile
deleted file mode 100644
index 4fdf05c..0000000
--- a/drivers/staging/qcache/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-qcache-y	:=	qcache-main.o tmem.o fmem.o
-
-obj-$(CONFIG_QCACHE)	+=	qcache.o
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
deleted file mode 100644
index 0609f4a..0000000
--- a/drivers/staging/qcache/fmem.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *
- * Copyright (c) 2011-2012, 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/export.h>
-#include <linux/fmem.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#ifdef CONFIG_MEMORY_HOTPLUG
-#include <linux/memory.h>
-#include <linux/memory_hotplug.h>
-#endif
-#include "tmem.h"
-#include <asm/mach/map.h>
-
-struct fmem_data fmem_data;
-enum fmem_state fmem_state;
-static spinlock_t fmem_state_lock;
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-static unsigned int section_powered_off[NR_MEM_SECTIONS];
-static unsigned int fmem_section_start, fmem_section_end;
-#endif
-
-void *fmem_map_virtual_area(int cacheability)
-{
-	unsigned long addr;
-	const struct mem_type *type;
-	int ret;
-
-	addr = (unsigned long) fmem_data.area->addr;
-	type = get_mem_type(cacheability);
-	ret = ioremap_pages(addr, fmem_data.phys, fmem_data.size, type);
-	if (ret)
-		return ERR_PTR(ret);
-
-	fmem_data.virt = fmem_data.area->addr;
-
-	return fmem_data.virt;
-}
-
-void fmem_unmap_virtual_area(void)
-{
-	unmap_kernel_range((unsigned long)fmem_data.virt, fmem_data.size);
-	fmem_data.virt = NULL;
-}
-
-static int fmem_probe(struct platform_device *pdev)
-{
-	struct fmem_platform_data *pdata = pdev->dev.platform_data;
-
-	if (!pdata->phys)
-		pdata->phys = allocate_contiguous_ebi_nomap(pdata->size,
-			pdata->align);
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-	fmem_section_start = pdata->phys >> PA_SECTION_SHIFT;
-	fmem_section_end = (pdata->phys - 1 + pdata->size) >> PA_SECTION_SHIFT;
-#endif
-	fmem_data.phys = pdata->phys + pdata->reserved_size_low;
-	fmem_data.size = pdata->size - pdata->reserved_size_low -
-					pdata->reserved_size_high;
-	fmem_data.reserved_size_low = pdata->reserved_size_low;
-	fmem_data.reserved_size_high = pdata->reserved_size_high;
-
-	if (!fmem_data.size)
-		return -ENODEV;
-
-	fmem_data.area = get_vm_area(fmem_data.size, VM_IOREMAP);
-	if (!fmem_data.area)
-		return -ENOMEM;
-
-	if (!fmem_map_virtual_area(MT_DEVICE_CACHED)) {
-		remove_vm_area(fmem_data.area->addr);
-		return -ENOMEM;
-	}
-	pr_info("fmem phys %lx virt %p size %lx\n",
-		fmem_data.phys, fmem_data.virt, fmem_data.size);
-
-	spin_lock_init(&fmem_state_lock);
-
-	return 0;
-}
-
-static int fmem_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver fmem_driver = {
-	.probe = fmem_probe,
-	.remove = fmem_remove,
-	.driver = { .name = "fmem" }
-};
-
-#ifdef CONFIG_SYSFS
-static ssize_t fmem_state_show(struct kobject *kobj,
-				    struct kobj_attribute *attr,
-				    char *buf)
-{
-	if (fmem_state == FMEM_T_STATE)
-		return snprintf(buf, 3, "t\n");
-	else if (fmem_state == FMEM_C_STATE)
-		return snprintf(buf, 3, "c\n");
-#ifdef CONFIG_MEMORY_HOTPLUG
-	else if (fmem_state == FMEM_O_STATE)
-		return snprintf(buf, 3, "o\n");
-#endif
-	else if (fmem_state == FMEM_UNINITIALIZED)
-		return snprintf(buf, 15, "uninitialized\n");
-	return snprintf(buf, 3, "?\n");
-}
-
-static ssize_t fmem_state_store(struct kobject *kobj,
-				    struct kobj_attribute *attr,
-				    const char *buf, size_t count)
-{
-	int ret = -EINVAL;
-
-	if (!strncmp(buf, "t", 1))
-		ret = fmem_set_state(FMEM_T_STATE);
-	else if (!strncmp(buf, "c", 1))
-		ret = fmem_set_state(FMEM_C_STATE);
-#ifdef CONFIG_MEMORY_HOTPLUG
-	else if (!strncmp(buf, "o", 1))
-		ret = fmem_set_state(FMEM_O_STATE);
-#endif
-	if (ret)
-		return ret;
-	return 1;
-}
-
-static struct kobj_attribute fmem_state_attr = {
-		.attr = { .name = "state", .mode = 0644 },
-		.show = fmem_state_show,
-		.store = fmem_state_store,
-};
-
-static struct attribute *fmem_attrs[] = {
-	&fmem_state_attr.attr,
-	NULL,
-};
-
-static struct attribute_group fmem_attr_group = {
-	.attrs = fmem_attrs,
-	.name = "fmem",
-};
-
-static int fmem_create_sysfs(void)
-{
-	int ret = 0;
-
-	ret = sysfs_create_group(mm_kobj, &fmem_attr_group);
-	if (ret)
-		pr_err("fmem: can't create sysfs\n");
-	return ret;
-}
-
-#endif
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-bool fmem_is_disjoint(unsigned long start_pfn, unsigned long nr_pages)
-{
-	unsigned long fmem_start_pfn, fmem_end_pfn;
-	unsigned long unstable_end_pfn;
-	unsigned long highest_start_pfn, lowest_end_pfn;
-
-	fmem_start_pfn = (fmem_data.phys - fmem_data.reserved_size_low)
-		>> PAGE_SHIFT;
-	fmem_end_pfn = (fmem_data.phys + fmem_data.size +
-		fmem_data.reserved_size_high - 1) >> PAGE_SHIFT;
-	unstable_end_pfn = start_pfn + nr_pages - 1;
-
-	highest_start_pfn = max(fmem_start_pfn, start_pfn);
-	lowest_end_pfn = min(fmem_end_pfn, unstable_end_pfn);
-
-	return lowest_end_pfn < highest_start_pfn;
-}
-
-static int fmem_mem_going_offline_callback(void *arg)
-{
-	struct memory_notify *marg = arg;
-
-	if (fmem_is_disjoint(marg->start_pfn, marg->nr_pages))
-		return 0;
-	return fmem_set_state(FMEM_O_STATE);
-}
-
-static void fmem_mem_online_callback(void *arg)
-{
-	struct memory_notify *marg = arg;
-	int i;
-
-	section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 0;
-
-	if (fmem_state != FMEM_O_STATE)
-		return;
-
-	for (i = fmem_section_start; i <= fmem_section_end; i++) {
-		if (section_powered_off[i])
-			return;
-	}
-
-	fmem_set_state(FMEM_T_STATE);
-}
-
-static void fmem_mem_offline_callback(void *arg)
-{
-	struct memory_notify *marg = arg;
-
-	section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 1;
-}
-
-static int fmem_memory_callback(struct notifier_block *self,
-				unsigned long action, void *arg)
-{
-	int ret = 0;
-
-	if (fmem_state == FMEM_UNINITIALIZED)
-		return NOTIFY_OK;
-
-	switch (action) {
-	case MEM_ONLINE:
-		fmem_mem_online_callback(arg);
-		break;
-	case MEM_GOING_OFFLINE:
-		ret = fmem_mem_going_offline_callback(arg);
-		break;
-	case MEM_OFFLINE:
-		fmem_mem_offline_callback(arg);
-		break;
-	case MEM_GOING_ONLINE:
-	case MEM_CANCEL_ONLINE:
-	case MEM_CANCEL_OFFLINE:
-		break;
-	}
-	if (ret)
-		ret = notifier_from_errno(ret);
-	else
-		ret = NOTIFY_OK;
-	return ret;
-}
-#endif
-
-static int __init fmem_init(void)
-{
-#ifdef CONFIG_MEMORY_HOTPLUG
-	hotplug_memory_notifier(fmem_memory_callback, 0);
-#endif
-	return platform_driver_register(&fmem_driver);
-}
-
-static void __exit fmem_exit(void)
-{
-	platform_driver_unregister(&fmem_driver);
-}
-
-struct fmem_data *fmem_get_info(void)
-{
-	return &fmem_data;
-}
-EXPORT_SYMBOL(fmem_get_info);
-
-void lock_fmem_state(void)
-{
-	spin_lock(&fmem_state_lock);
-}
-
-void unlock_fmem_state(void)
-{
-	spin_unlock(&fmem_state_lock);
-}
-
-int fmem_set_state(enum fmem_state new_state)
-{
-	int ret = 0;
-	int create_sysfs = 0;
-
-	lock_fmem_state();
-	if (fmem_state == new_state)
-		goto out;
-
-	if (fmem_state == FMEM_UNINITIALIZED) {
-		if (new_state == FMEM_T_STATE) {
-			tmem_enable();
-			create_sysfs = 1;
-			goto out_set;
-		} else {
-			ret = -EINVAL;
-			goto out;
-		}
-	}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-	if (fmem_state == FMEM_C_STATE && new_state == FMEM_O_STATE) {
-		ret = -EAGAIN;
-		goto out;
-	}
-
-	if (fmem_state == FMEM_O_STATE && new_state == FMEM_C_STATE) {
-		pr_warn("attempting to use powered off memory as fmem\n");
-		ret = -EAGAIN;
-		goto out;
-	}
-#endif
-
-	if (new_state == FMEM_T_STATE) {
-		void *v;
-		v = fmem_map_virtual_area(MT_DEVICE_CACHED);
-		if (IS_ERR_OR_NULL(v)) {
-			ret = PTR_ERR(v);
-			goto out;
-		}
-		tmem_enable();
-	} else {
-		tmem_disable();
-		fmem_unmap_virtual_area();
-	}
-
-out_set:
-	fmem_state = new_state;
-out:
-	unlock_fmem_state();
-#ifdef CONFIG_SYSFS
-	if (create_sysfs)
-		fmem_create_sysfs();
-#endif
-	return ret;
-}
-EXPORT_SYMBOL(fmem_set_state);
-
-arch_initcall(fmem_init);
-module_exit(fmem_exit);
diff --git a/drivers/staging/qcache/qcache-main.c b/drivers/staging/qcache/qcache-main.c
deleted file mode 100644
index f416cfc..0000000
--- a/drivers/staging/qcache/qcache-main.c
+++ /dev/null
@@ -1,1358 +0,0 @@
-/*
- * Copyright (c) 2010,2011, Dan Magenheimer, Oracle Corp.
- * Copyright (c) 2010,2011, Nitin Gupta
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * Qcache provides an in-kernel "host implementation" for transcendent memory
- * and, thus indirectly, for cleancache and frontswap.  Qcache includes a
- * page-accessible memory [1] interface, utilizing lzo1x compression:
- * 1) "compression buddies" ("zbud") is used for ephemeral pages
- * Zbud allows pairs (and potentially,
- * in the future, more than a pair of) compressed pages to be closely linked
- * so that reclaiming can be done via the kernel's physical-page-oriented
- * "shrinker" interface.
- *
- * [1] For a definition of page-accessible memory (aka PAM), see:
- *   http://marc.info/?l=linux-mm&m=127811271605009
- */
-
-#include <linux/module.h>
-#include <linux/cpu.h>
-#include <linux/highmem.h>
-#include <linux/list.h>
-#include <linux/lzo.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/atomic.h>
-#include <linux/math64.h>
-#include <linux/bitmap.h>
-#include <linux/fmem.h>
-#include "tmem.h"
-
-#if !defined(CONFIG_CLEANCACHE)
-#error "qcache is useless without CONFIG_CLEANCACHE"
-#endif
-#include <linux/cleancache.h>
-
-#define ZCACHE_GFP_MASK \
-	(__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC)
-
-#define MAX_POOLS_PER_CLIENT 16
-
-#define MAX_CLIENTS 16
-#define LOCAL_CLIENT ((uint16_t)-1)
-
-MODULE_LICENSE("GPL");
-
-struct zcache_client {
-	struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
-	struct xv_pool *xvpool;
-	bool allocated;
-	atomic_t refcount;
-};
-
-struct qcache_info {
-	void *addr;
-	unsigned long *bitmap;
-	spinlock_t lock;
-	unsigned pages;
-};
-static struct qcache_info qcache_info;
-static unsigned long zcache_qc_allocated;
-static unsigned long zcache_qc_freed;
-static unsigned long zcache_qc_used;
-static unsigned long zcache_qc_max_used;
-
-static struct zcache_client zcache_host;
-static struct zcache_client zcache_clients[MAX_CLIENTS];
-
-static inline uint16_t get_client_id_from_client(struct zcache_client *cli)
-{
-	BUG_ON(cli == NULL);
-	if (cli == &zcache_host)
-		return LOCAL_CLIENT;
-	return cli - &zcache_clients[0];
-}
-
-static inline bool is_local_client(struct zcache_client *cli)
-{
-	return cli == &zcache_host;
-}
-
-/**********
- * Compression buddies ("zbud") provides for packing two (or, possibly
- * in the future, more) compressed ephemeral pages into a single "raw"
- * (physical) page and tracking them with data structures so that
- * the raw pages can be easily reclaimed.
- *
- * A zbud page ("zbpg") is an aligned page containing a list_head,
- * a lock, and two "zbud headers".  The remainder of the physical
- * page is divided up into aligned 64-byte "chunks" which contain
- * the compressed data for zero, one, or two zbuds.  Each zbpg
- * resides on: (1) an "unused list" if it has no zbuds; (2) a
- * "buddied" list if it is fully populated  with two zbuds; or
- * (3) one of PAGE_SIZE/64 "unbuddied" lists indexed by how many chunks
- * the one unbuddied zbud uses.  The data inside a zbpg cannot be
- * read or written unless the zbpg's lock is held.
- */
-
-#define ZBH_SENTINEL  0x43214321
-#define ZBPG_SENTINEL  0xdeadbeef
-
-#define ZBUD_MAX_BUDS 2
-
-struct zbud_hdr {
-	uint16_t client_id;
-	uint16_t pool_id;
-	struct tmem_oid oid;
-	uint32_t index;
-	uint16_t size; /* compressed size in bytes, zero means unused */
-	DECL_SENTINEL
-};
-
-struct zbud_page {
-	struct list_head bud_list;
-	spinlock_t lock;
-	struct zbud_hdr buddy[ZBUD_MAX_BUDS];
-	DECL_SENTINEL
-	/* followed by NUM_CHUNK aligned CHUNK_SIZE-byte chunks */
-};
-
-#define CHUNK_SHIFT	6
-#define CHUNK_SIZE	(1 << CHUNK_SHIFT)
-#define CHUNK_MASK	(~(CHUNK_SIZE-1))
-#define NCHUNKS		(((PAGE_SIZE - sizeof(struct zbud_page)) & \
-				CHUNK_MASK) >> CHUNK_SHIFT)
-#define MAX_CHUNK	(NCHUNKS-1)
-
-static struct {
-	struct list_head list;
-	unsigned count;
-} zbud_unbuddied[NCHUNKS];
-/* list N contains pages with N chunks USED and NCHUNKS-N unused */
-/* element 0 is never used but optimizing that isn't worth it */
-static unsigned long zbud_cumul_chunk_counts[NCHUNKS];
-
-struct list_head zbud_buddied_list;
-static unsigned long zcache_zbud_buddied_count;
-
-/* protects the buddied list and all unbuddied lists */
-static DEFINE_SPINLOCK(zbud_budlists_spinlock);
-
-static atomic_t zcache_zbud_curr_raw_pages;
-static atomic_t zcache_zbud_curr_zpages;
-static unsigned long zcache_zbud_curr_zbytes;
-static unsigned long zcache_zbud_cumul_zpages;
-static unsigned long zcache_zbud_cumul_zbytes;
-static unsigned long zcache_compress_poor;
-static unsigned long zcache_mean_compress_poor;
-
-/* forward references */
-static void *zcache_get_free_page(void);
-
-static void *qcache_alloc(void)
-{
-	void *addr;
-	unsigned long flags;
-	int offset;
-	struct qcache_info *qc = &qcache_info;
-
-	spin_lock_irqsave(&qc->lock, flags);
-	offset = bitmap_find_free_region(qc->bitmap, qc->pages, 0);
-
-	if (offset < 0) {
-		spin_unlock_irqrestore(&qc->lock, flags);
-		return NULL;
-	}
-
-	zcache_qc_allocated++;
-	zcache_qc_used++;
-	zcache_qc_max_used = max(zcache_qc_max_used, zcache_qc_used);
-	spin_unlock_irqrestore(&qc->lock, flags);
-
-	addr = qc->addr + offset * PAGE_SIZE;
-
-	return addr;
-}
-
-static void qcache_free(void *addr)
-{
-	unsigned long flags;
-	int offset;
-	struct qcache_info *qc = &qcache_info;
-
-	offset = (addr - qc->addr) / PAGE_SIZE;
-
-	spin_lock_irqsave(&qc->lock, flags);
-	bitmap_release_region(qc->bitmap, offset, 0);
-
-	zcache_qc_freed++;
-	zcache_qc_used--;
-	spin_unlock_irqrestore(&qc->lock, flags);
-}
-
-/*
- * zbud helper functions
- */
-
-static inline unsigned zbud_max_buddy_size(void)
-{
-	return MAX_CHUNK << CHUNK_SHIFT;
-}
-
-static inline unsigned zbud_size_to_chunks(unsigned size)
-{
-	BUG_ON(size == 0 || size > zbud_max_buddy_size());
-	return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT;
-}
-
-static inline int zbud_budnum(struct zbud_hdr *zh)
-{
-	unsigned offset = (unsigned long)zh & (PAGE_SIZE - 1);
-	struct zbud_page *zbpg = NULL;
-	unsigned budnum = -1U;
-	int i;
-
-	for (i = 0; i < ZBUD_MAX_BUDS; i++)
-		if (offset == offsetof(typeof(*zbpg), buddy[i])) {
-			budnum = i;
-			break;
-		}
-	BUG_ON(budnum == -1U);
-	return budnum;
-}
-
-static char *zbud_data(struct zbud_hdr *zh, unsigned size)
-{
-	struct zbud_page *zbpg;
-	char *p;
-	unsigned budnum;
-
-	ASSERT_SENTINEL(zh, ZBH);
-	budnum = zbud_budnum(zh);
-	BUG_ON(size == 0 || size > zbud_max_buddy_size());
-	zbpg = container_of(zh, struct zbud_page, buddy[budnum]);
-	p = (char *)zbpg;
-	if (budnum == 0)
-		p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) &
-							CHUNK_MASK);
-	else if (budnum == 1)
-		p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK);
-	return p;
-}
-
-/*
- * zbud raw page management
- */
-
-static struct zbud_page *zbud_alloc_raw_page(void)
-{
-	struct zbud_page *zbpg = NULL;
-	struct zbud_hdr *zh0, *zh1;
-
-	zbpg = zcache_get_free_page();
-	if (likely(zbpg != NULL)) {
-		INIT_LIST_HEAD(&zbpg->bud_list);
-		zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1];
-		spin_lock_init(&zbpg->lock);
-		atomic_inc(&zcache_zbud_curr_raw_pages);
-		INIT_LIST_HEAD(&zbpg->bud_list);
-		SET_SENTINEL(zbpg, ZBPG);
-		zh0->size = 0; zh1->size = 0;
-		tmem_oid_set_invalid(&zh0->oid);
-		tmem_oid_set_invalid(&zh1->oid);
-	}
-	return zbpg;
-}
-
-static void zbud_free_raw_page(struct zbud_page *zbpg)
-{
-	struct zbud_hdr *zh0 = &zbpg->buddy[0], *zh1 = &zbpg->buddy[1];
-
-	ASSERT_SENTINEL(zbpg, ZBPG);
-	BUG_ON(!list_empty(&zbpg->bud_list));
-	BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid));
-	BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid));
-	INVERT_SENTINEL(zbpg, ZBPG);
-	spin_unlock(&zbpg->lock);
-	qcache_free(zbpg);
-}
-
-/*
- * core zbud handling routines
- */
-
-static unsigned zbud_free(struct zbud_hdr *zh)
-{
-	unsigned size;
-
-	ASSERT_SENTINEL(zh, ZBH);
-	BUG_ON(!tmem_oid_valid(&zh->oid));
-	size = zh->size;
-	BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size());
-	zh->size = 0;
-	tmem_oid_set_invalid(&zh->oid);
-	INVERT_SENTINEL(zh, ZBH);
-	zcache_zbud_curr_zbytes -= size;
-	atomic_dec(&zcache_zbud_curr_zpages);
-	return size;
-}
-
-static void zbud_free_and_delist(struct zbud_hdr *zh)
-{
-	unsigned chunks;
-	struct zbud_hdr *zh_other;
-	unsigned budnum = zbud_budnum(zh), size;
-	struct zbud_page *zbpg =
-		container_of(zh, struct zbud_page, buddy[budnum]);
-
-	spin_lock(&zbpg->lock);
-	if (list_empty(&zbpg->bud_list)) {
-		spin_unlock(&zbpg->lock);
-		return;
-	}
-	size = zbud_free(zh);
-	zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0];
-	if (zh_other->size == 0) { /* was unbuddied: unlist and free */
-		chunks = zbud_size_to_chunks(size) ;
-		spin_lock(&zbud_budlists_spinlock);
-		BUG_ON(list_empty(&zbud_unbuddied[chunks].list));
-		list_del_init(&zbpg->bud_list);
-		zbud_unbuddied[chunks].count--;
-		spin_unlock(&zbud_budlists_spinlock);
-		zbud_free_raw_page(zbpg);
-	} else { /* was buddied: move remaining buddy to unbuddied list */
-		chunks = zbud_size_to_chunks(zh_other->size) ;
-		spin_lock(&zbud_budlists_spinlock);
-		list_del_init(&zbpg->bud_list);
-		zcache_zbud_buddied_count--;
-		list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list);
-		zbud_unbuddied[chunks].count++;
-		spin_unlock(&zbud_budlists_spinlock);
-		spin_unlock(&zbpg->lock);
-	}
-}
-
-static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id,
-					struct tmem_oid *oid,
-					uint32_t index, struct page *page,
-					void *cdata, unsigned size)
-{
-	struct zbud_hdr *zh0, *zh1, *zh = NULL;
-	struct zbud_page *zbpg = NULL, *ztmp;
-	unsigned nchunks;
-	char *to;
-	int i, found_good_buddy = 0;
-
-	nchunks = zbud_size_to_chunks(size) ;
-	for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) {
-		spin_lock(&zbud_budlists_spinlock);
-		if (!list_empty(&zbud_unbuddied[i].list)) {
-			list_for_each_entry_safe(zbpg, ztmp,
-				    &zbud_unbuddied[i].list, bud_list) {
-				if (spin_trylock(&zbpg->lock)) {
-					found_good_buddy = i;
-					goto found_unbuddied;
-				}
-			}
-		}
-		spin_unlock(&zbud_budlists_spinlock);
-	}
-	/* didn't find a good buddy, try allocating a new page */
-	zbpg = zbud_alloc_raw_page();
-	if (unlikely(zbpg == NULL))
-		goto out;
-	/* ok, have a page, now compress the data before taking locks */
-	spin_lock(&zbpg->lock);
-	spin_lock(&zbud_budlists_spinlock);
-	list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list);
-	zbud_unbuddied[nchunks].count++;
-	zh = &zbpg->buddy[0];
-	goto init_zh;
-
-found_unbuddied:
-	zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1];
-	BUG_ON(!((zh0->size == 0) ^ (zh1->size == 0)));
-	if (zh0->size != 0) { /* buddy0 in use, buddy1 is vacant */
-		ASSERT_SENTINEL(zh0, ZBH);
-		zh = zh1;
-	} else if (zh1->size != 0) { /* buddy1 in use, buddy0 is vacant */
-		ASSERT_SENTINEL(zh1, ZBH);
-		zh = zh0;
-	} else
-		BUG();
-	list_del_init(&zbpg->bud_list);
-	zbud_unbuddied[found_good_buddy].count--;
-	list_add_tail(&zbpg->bud_list, &zbud_buddied_list);
-	zcache_zbud_buddied_count++;
-
-init_zh:
-	SET_SENTINEL(zh, ZBH);
-	zh->size = size;
-	zh->index = index;
-	zh->oid = *oid;
-	zh->pool_id = pool_id;
-	zh->client_id = client_id;
-	/* can wait to copy the data until the list locks are dropped */
-	spin_unlock(&zbud_budlists_spinlock);
-
-	to = zbud_data(zh, size);
-	memcpy(to, cdata, size);
-	spin_unlock(&zbpg->lock);
-	zbud_cumul_chunk_counts[nchunks]++;
-	atomic_inc(&zcache_zbud_curr_zpages);
-	zcache_zbud_cumul_zpages++;
-	zcache_zbud_curr_zbytes += size;
-	zcache_zbud_cumul_zbytes += size;
-out:
-	return zh;
-}
-
-static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
-{
-	struct zbud_page *zbpg;
-	unsigned budnum = zbud_budnum(zh);
-	size_t out_len = PAGE_SIZE;
-	char *to_va, *from_va;
-	unsigned size;
-	int ret = 0;
-
-	zbpg = container_of(zh, struct zbud_page, buddy[budnum]);
-	spin_lock(&zbpg->lock);
-	if (list_empty(&zbpg->bud_list)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	ASSERT_SENTINEL(zh, ZBH);
-	BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size());
-	to_va = kmap_atomic(page);
-	size = zh->size;
-	from_va = zbud_data(zh, size);
-	ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len);
-	BUG_ON(ret != LZO_E_OK);
-	BUG_ON(out_len != PAGE_SIZE);
-	kunmap_atomic(to_va);
-out:
-	spin_unlock(&zbpg->lock);
-	return ret;
-}
-
-static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id,
-						uint16_t poolid);
-static void zcache_put_pool(struct tmem_pool *pool);
-
-static void zbud_init(void)
-{
-	int i;
-
-	INIT_LIST_HEAD(&zbud_buddied_list);
-	zcache_zbud_buddied_count = 0;
-	for (i = 0; i < NCHUNKS; i++) {
-		INIT_LIST_HEAD(&zbud_unbuddied[i].list);
-		zbud_unbuddied[i].count = 0;
-	}
-}
-
-#ifdef CONFIG_SYSFS
-/*
- * These sysfs routines show a nice distribution of how many zbpg's are
- * currently (and have ever been placed) in each unbuddied list.  It's fun
- * to watch but can probably go away before final merge.
- */
-static int zbud_show_unbuddied_list_counts(char *buf)
-{
-	int i;
-	char *p = buf;
-
-	for (i = 0; i < NCHUNKS; i++)
-		p += sprintf(p, "%u ", zbud_unbuddied[i].count);
-	return p - buf;
-}
-
-static int zbud_show_cumul_chunk_counts(char *buf)
-{
-	unsigned long i, chunks = 0, total_chunks = 0, sum_total_chunks = 0;
-	unsigned long total_chunks_lte_21 = 0, total_chunks_lte_32 = 0;
-	unsigned long total_chunks_lte_42 = 0;
-	char *p = buf;
-
-	for (i = 0; i < NCHUNKS; i++) {
-		p += sprintf(p, "%lu ", zbud_cumul_chunk_counts[i]);
-		chunks += zbud_cumul_chunk_counts[i];
-		total_chunks += zbud_cumul_chunk_counts[i];
-		sum_total_chunks += i * zbud_cumul_chunk_counts[i];
-		if (i == 21)
-			total_chunks_lte_21 = total_chunks;
-		if (i == 32)
-			total_chunks_lte_32 = total_chunks;
-		if (i == 42)
-			total_chunks_lte_42 = total_chunks;
-	}
-	p += sprintf(p, "<=21:%lu <=32:%lu <=42:%lu, mean:%lu\n",
-		total_chunks_lte_21, total_chunks_lte_32, total_chunks_lte_42,
-		chunks == 0 ? 0 : sum_total_chunks / chunks);
-	return p - buf;
-}
-#endif
-
-/*
- * zcache core code starts here
- */
-
-/* useful stats not collected by cleancache or frontswap */
-static unsigned long zcache_flush_total;
-static unsigned long zcache_flush_found;
-static unsigned long zcache_flobj_total;
-static unsigned long zcache_flobj_found;
-static unsigned long zcache_failed_eph_puts;
-
-/*
- * Tmem operations assume the poolid implies the invoking client.
- * Zcache only has one client (the kernel itself): LOCAL_CLIENT.
- * RAMster has each client numbered by cluster node, and a KVM version
- * of zcache would have one client per guest and each client might
- * have a poolid==N.
- */
-static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid)
-{
-	struct tmem_pool *pool = NULL;
-	struct zcache_client *cli = NULL;
-
-	if (cli_id == LOCAL_CLIENT)
-		cli = &zcache_host;
-	else {
-		if (cli_id >= MAX_CLIENTS)
-			goto out;
-		cli = &zcache_clients[cli_id];
-		if (cli == NULL)
-			goto out;
-		atomic_inc(&cli->refcount);
-	}
-	if (poolid < MAX_POOLS_PER_CLIENT) {
-		pool = cli->tmem_pools[poolid];
-		if (pool != NULL)
-			atomic_inc(&pool->refcount);
-	}
-out:
-	return pool;
-}
-
-static void zcache_put_pool(struct tmem_pool *pool)
-{
-	struct zcache_client *cli = NULL;
-
-	if (pool == NULL)
-		BUG();
-	cli = pool->client;
-	atomic_dec(&pool->refcount);
-	atomic_dec(&cli->refcount);
-}
-
-int zcache_new_client(uint16_t cli_id)
-{
-	struct zcache_client *cli = NULL;
-	int ret = -1;
-
-	if (cli_id == LOCAL_CLIENT)
-		cli = &zcache_host;
-	else if ((unsigned int)cli_id < MAX_CLIENTS)
-		cli = &zcache_clients[cli_id];
-	if (cli == NULL)
-		goto out;
-	if (cli->allocated)
-		goto out;
-	cli->allocated = 1;
-	ret = 0;
-out:
-	return ret;
-}
-
-/* counters for debugging */
-static unsigned long zcache_failed_get_free_pages;
-static unsigned long zcache_failed_alloc;
-static unsigned long zcache_put_to_flush;
-static unsigned long zcache_aborted_preload;
-static unsigned long zcache_aborted_shrink;
-
-/*
- * Ensure that memory allocation requests in zcache don't result
- * in direct reclaim requests via the shrinker, which would cause
- * an infinite loop.  Maybe a GFP flag would be better?
- */
-static DEFINE_SPINLOCK(zcache_direct_reclaim_lock);
-
-/*
- * for now, used named slabs so can easily track usage; later can
- * either just use kmalloc, or perhaps add a slab-like allocator
- * to more carefully manage total memory utilization
- */
-static struct kmem_cache *zcache_objnode_cache;
-static struct kmem_cache *zcache_obj_cache;
-static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0);
-static unsigned long zcache_curr_obj_count_max;
-static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0);
-static unsigned long zcache_curr_objnode_count_max;
-
-/*
- * to avoid memory allocation recursion (e.g. due to direct reclaim), we
- * preload all necessary data structures so the hostops callbacks never
- * actually do a malloc
- */
-struct zcache_preload {
-	void *page;
-	struct tmem_obj *obj;
-	int nr;
-	struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH];
-};
-static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, };
-
-static int zcache_do_preload(struct tmem_pool *pool)
-{
-	struct zcache_preload *kp;
-	struct tmem_objnode *objnode;
-	struct tmem_obj *obj;
-	void *page;
-	int ret = -ENOMEM;
-
-	if (unlikely(zcache_objnode_cache == NULL))
-		goto out;
-	if (unlikely(zcache_obj_cache == NULL))
-		goto out;
-	if (!spin_trylock(&zcache_direct_reclaim_lock)) {
-		zcache_aborted_preload++;
-		goto out;
-	}
-	preempt_disable();
-	kp = &__get_cpu_var(zcache_preloads);
-	while (kp->nr < ARRAY_SIZE(kp->objnodes)) {
-		preempt_enable_no_resched();
-		objnode = kmem_cache_alloc(zcache_objnode_cache,
-				ZCACHE_GFP_MASK);
-		if (unlikely(objnode == NULL)) {
-			zcache_failed_alloc++;
-			goto unlock_out;
-		}
-		preempt_disable();
-		kp = &__get_cpu_var(zcache_preloads);
-		if (kp->nr < ARRAY_SIZE(kp->objnodes))
-			kp->objnodes[kp->nr++] = objnode;
-		else
-			kmem_cache_free(zcache_objnode_cache, objnode);
-	}
-	preempt_enable_no_resched();
-	obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK);
-	if (unlikely(obj == NULL)) {
-		zcache_failed_alloc++;
-		goto unlock_out;
-	}
-	page = qcache_alloc();
-	if (unlikely(page == NULL)) {
-		zcache_failed_get_free_pages++;
-		kmem_cache_free(zcache_obj_cache, obj);
-		goto unlock_out;
-	}
-	preempt_disable();
-	kp = &__get_cpu_var(zcache_preloads);
-	if (kp->obj == NULL)
-		kp->obj = obj;
-	else
-		kmem_cache_free(zcache_obj_cache, obj);
-	if (kp->page == NULL)
-		kp->page = page;
-	else
-		qcache_free(page);
-	ret = 0;
-unlock_out:
-	spin_unlock(&zcache_direct_reclaim_lock);
-out:
-	return ret;
-}
-
-static void *zcache_get_free_page(void)
-{
-	struct zcache_preload *kp;
-	void *page;
-
-	kp = &__get_cpu_var(zcache_preloads);
-	page = kp->page;
-	BUG_ON(page == NULL);
-	kp->page = NULL;
-	return page;
-}
-
-/*
- * zcache implementation for tmem host ops
- */
-
-static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool)
-{
-	struct tmem_objnode *objnode = NULL;
-	unsigned long count;
-	struct zcache_preload *kp;
-
-	kp = &__get_cpu_var(zcache_preloads);
-	if (kp->nr <= 0)
-		goto out;
-	objnode = kp->objnodes[kp->nr - 1];
-	BUG_ON(objnode == NULL);
-	kp->objnodes[kp->nr - 1] = NULL;
-	kp->nr--;
-	count = atomic_inc_return(&zcache_curr_objnode_count);
-	if (count > zcache_curr_objnode_count_max)
-		zcache_curr_objnode_count_max = count;
-out:
-	return objnode;
-}
-
-static void zcache_objnode_free(struct tmem_objnode *objnode,
-					struct tmem_pool *pool)
-{
-	atomic_dec(&zcache_curr_objnode_count);
-	BUG_ON(atomic_read(&zcache_curr_objnode_count) < 0);
-	kmem_cache_free(zcache_objnode_cache, objnode);
-}
-
-static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool)
-{
-	struct tmem_obj *obj = NULL;
-	unsigned long count;
-	struct zcache_preload *kp;
-
-	kp = &__get_cpu_var(zcache_preloads);
-	obj = kp->obj;
-	BUG_ON(obj == NULL);
-	kp->obj = NULL;
-	count = atomic_inc_return(&zcache_curr_obj_count);
-	if (count > zcache_curr_obj_count_max)
-		zcache_curr_obj_count_max = count;
-	return obj;
-}
-
-static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool)
-{
-	atomic_dec(&zcache_curr_obj_count);
-	BUG_ON(atomic_read(&zcache_curr_obj_count) < 0);
-	kmem_cache_free(zcache_obj_cache, obj);
-}
-
-static void zcache_flush_all_obj(void)
-{
-	struct tmem_pool *pool;
-	int pool_id;
-	struct zcache_preload *kp;
-
-	kp = &__get_cpu_var(zcache_preloads);
-
-	for (pool_id = 0; pool_id < MAX_POOLS_PER_CLIENT; pool_id++) {
-		pool = zcache_get_pool_by_id(LOCAL_CLIENT, pool_id);
-		tmem_flush_pool(pool);
-		if (pool)
-			zcache_put_pool(pool);
-	}
-	if (kp->page) {
-		qcache_free(kp->page);
-		kp->page = NULL;
-	}
-	if (zcache_qc_used)
-		pr_warn("pages used not 0 after qcache flush all, is %ld\n",
-			zcache_qc_used);
-}
-
-/*
- * When zcache is disabled ("frozen"), pools can be created and destroyed,
- * but all puts (and thus all other operations that require memory allocation)
- * must fail.  If zcache is unfrozen, accepts puts, then frozen again,
- * data consistency requires all puts while frozen to be converted into
- * flushes.
- */
-static bool zcache_freeze;
-
-static void zcache_control(bool freeze)
-{
-	zcache_freeze = freeze;
-}
-
-static struct tmem_hostops zcache_hostops = {
-	.obj_alloc = zcache_obj_alloc,
-	.obj_free = zcache_obj_free,
-	.objnode_alloc = zcache_objnode_alloc,
-	.objnode_free = zcache_objnode_free,
-	.flush_all_obj = zcache_flush_all_obj,
-	.control = zcache_control,
-};
-
-/*
- * zcache implementations for PAM page descriptor ops
- */
-
-static atomic_t zcache_curr_eph_pampd_count = ATOMIC_INIT(0);
-static unsigned long zcache_curr_eph_pampd_count_max;
-
-/* forward reference */
-static int zcache_compress(struct page *from, void **out_va, size_t *out_len);
-
-static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph,
-				struct tmem_pool *pool, struct tmem_oid *oid,
-				 uint32_t index)
-{
-	void *pampd = NULL, *cdata;
-	size_t clen;
-	int ret;
-	unsigned long count;
-	struct page *page = (struct page *)(data);
-	struct zcache_client *cli = pool->client;
-	uint16_t client_id = get_client_id_from_client(cli);
-
-	ret = zcache_compress(page, &cdata, &clen);
-	if (ret == 0)
-		goto out;
-	if (clen == 0 || clen > zbud_max_buddy_size()) {
-		zcache_compress_poor++;
-		goto out;
-	}
-	pampd = (void *)zbud_create(client_id, pool->pool_id, oid,
-					index, page, cdata, clen);
-	if (pampd != NULL) {
-		count = atomic_inc_return(&zcache_curr_eph_pampd_count);
-		if (count > zcache_curr_eph_pampd_count_max)
-			zcache_curr_eph_pampd_count_max = count;
-	}
-out:
-	return pampd;
-}
-
-/*
- * fill the pageframe corresponding to the struct page with the data
- * from the passed pampd
- */
-static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw,
-					void *pampd, struct tmem_pool *pool,
-					struct tmem_oid *oid, uint32_t index)
-{
-	BUG();
-	return 0;
-}
-
-/*
- * fill the pageframe corresponding to the struct page with the data
- * from the passed pampd
- */
-static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw,
-					void *pampd, struct tmem_pool *pool,
-					struct tmem_oid *oid, uint32_t index)
-{
-	int ret = 0;
-
-	zbud_decompress((struct page *)(data), pampd);
-	zbud_free_and_delist((struct zbud_hdr *)pampd);
-	atomic_dec(&zcache_curr_eph_pampd_count);
-	return ret;
-}
-
-/*
- * free the pampd and remove it from any zcache lists
- * pampd must no longer be pointed to from any tmem data structures!
- */
-static void zcache_pampd_free(void *pampd, struct tmem_pool *pool,
-				struct tmem_oid *oid, uint32_t index)
-{
-	zbud_free_and_delist((struct zbud_hdr *)pampd);
-	atomic_dec(&zcache_curr_eph_pampd_count);
-	BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0);
-}
-
-static void zcache_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj)
-{
-}
-
-static void zcache_pampd_new_obj(struct tmem_obj *obj)
-{
-}
-
-static int zcache_pampd_replace_in_obj(void *pampd, struct tmem_obj *obj)
-{
-	return -1;
-}
-
-static bool zcache_pampd_is_remote(void *pampd)
-{
-	return 0;
-}
-
-static struct tmem_pamops zcache_pamops = {
-	.create = zcache_pampd_create,
-	.get_data = zcache_pampd_get_data,
-	.get_data_and_free = zcache_pampd_get_data_and_free,
-	.free = zcache_pampd_free,
-	.free_obj = zcache_pampd_free_obj,
-	.new_obj = zcache_pampd_new_obj,
-	.replace_in_obj = zcache_pampd_replace_in_obj,
-	.is_remote = zcache_pampd_is_remote,
-};
-
-/*
- * zcache compression/decompression and related per-cpu stuff
- */
-
-#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS
-#define LZO_DSTMEM_PAGE_ORDER 1
-static DEFINE_PER_CPU(unsigned char *, zcache_workmem);
-static DEFINE_PER_CPU(unsigned char *, zcache_dstmem);
-
-static int zcache_compress(struct page *from, void **out_va, size_t *out_len)
-{
-	int ret = 0;
-	unsigned char *dmem = __get_cpu_var(zcache_dstmem);
-	unsigned char *wmem = __get_cpu_var(zcache_workmem);
-	char *from_va;
-
-	BUG_ON(!irqs_disabled());
-	if (unlikely(dmem == NULL || wmem == NULL))
-		goto out;  /* no buffer, so can't compress */
-	from_va = kmap_atomic(from);
-	mb();
-	ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem);
-	BUG_ON(ret != LZO_E_OK);
-	*out_va = dmem;
-	kunmap_atomic(from_va);
-	ret = 1;
-out:
-	return ret;
-}
-
-#ifdef CONFIG_SYSFS
-#define ZCACHE_SYSFS_RO(_name) \
-	static ssize_t zcache_##_name##_show(struct kobject *kobj, \
-				struct kobj_attribute *attr, char *buf) \
-	{ \
-		return sprintf(buf, "%lu\n", zcache_##_name); \
-	} \
-	static struct kobj_attribute zcache_##_name##_attr = { \
-		.attr = { .name = __stringify(_name), .mode = 0444 }, \
-		.show = zcache_##_name##_show, \
-	}
-
-#define ZCACHE_SYSFS_RO_ATOMIC(_name) \
-	static ssize_t zcache_##_name##_show(struct kobject *kobj, \
-				struct kobj_attribute *attr, char *buf) \
-	{ \
-	    return sprintf(buf, "%d\n", atomic_read(&zcache_##_name)); \
-	} \
-	static struct kobj_attribute zcache_##_name##_attr = { \
-		.attr = { .name = __stringify(_name), .mode = 0444 }, \
-		.show = zcache_##_name##_show, \
-	}
-
-#define ZCACHE_SYSFS_RO_CUSTOM(_name, _func) \
-	static ssize_t zcache_##_name##_show(struct kobject *kobj, \
-				struct kobj_attribute *attr, char *buf) \
-	{ \
-	    return _func(buf); \
-	} \
-	static struct kobj_attribute zcache_##_name##_attr = { \
-		.attr = { .name = __stringify(_name), .mode = 0444 }, \
-		.show = zcache_##_name##_show, \
-	}
-
-ZCACHE_SYSFS_RO(curr_obj_count_max);
-ZCACHE_SYSFS_RO(curr_objnode_count_max);
-ZCACHE_SYSFS_RO(flush_total);
-ZCACHE_SYSFS_RO(flush_found);
-ZCACHE_SYSFS_RO(flobj_total);
-ZCACHE_SYSFS_RO(flobj_found);
-ZCACHE_SYSFS_RO(failed_eph_puts);
-ZCACHE_SYSFS_RO(zbud_curr_zbytes);
-ZCACHE_SYSFS_RO(zbud_cumul_zpages);
-ZCACHE_SYSFS_RO(zbud_cumul_zbytes);
-ZCACHE_SYSFS_RO(zbud_buddied_count);
-ZCACHE_SYSFS_RO(failed_get_free_pages);
-ZCACHE_SYSFS_RO(failed_alloc);
-ZCACHE_SYSFS_RO(put_to_flush);
-ZCACHE_SYSFS_RO(aborted_preload);
-ZCACHE_SYSFS_RO(aborted_shrink);
-ZCACHE_SYSFS_RO(compress_poor);
-ZCACHE_SYSFS_RO(mean_compress_poor);
-ZCACHE_SYSFS_RO(qc_allocated);
-ZCACHE_SYSFS_RO(qc_freed);
-ZCACHE_SYSFS_RO(qc_used);
-ZCACHE_SYSFS_RO(qc_max_used);
-ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages);
-ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages);
-ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count);
-ZCACHE_SYSFS_RO_ATOMIC(curr_objnode_count);
-ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts,
-			zbud_show_unbuddied_list_counts);
-ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts,
-			zbud_show_cumul_chunk_counts);
-
-static struct attribute *qcache_attrs[] = {
-	&zcache_curr_obj_count_attr.attr,
-	&zcache_curr_obj_count_max_attr.attr,
-	&zcache_curr_objnode_count_attr.attr,
-	&zcache_curr_objnode_count_max_attr.attr,
-	&zcache_flush_total_attr.attr,
-	&zcache_flobj_total_attr.attr,
-	&zcache_flush_found_attr.attr,
-	&zcache_flobj_found_attr.attr,
-	&zcache_failed_eph_puts_attr.attr,
-	&zcache_compress_poor_attr.attr,
-	&zcache_mean_compress_poor_attr.attr,
-	&zcache_zbud_curr_raw_pages_attr.attr,
-	&zcache_zbud_curr_zpages_attr.attr,
-	&zcache_zbud_curr_zbytes_attr.attr,
-	&zcache_zbud_cumul_zpages_attr.attr,
-	&zcache_zbud_cumul_zbytes_attr.attr,
-	&zcache_zbud_buddied_count_attr.attr,
-	&zcache_failed_get_free_pages_attr.attr,
-	&zcache_failed_alloc_attr.attr,
-	&zcache_put_to_flush_attr.attr,
-	&zcache_aborted_preload_attr.attr,
-	&zcache_aborted_shrink_attr.attr,
-	&zcache_zbud_unbuddied_list_counts_attr.attr,
-	&zcache_zbud_cumul_chunk_counts_attr.attr,
-	&zcache_qc_allocated_attr.attr,
-	&zcache_qc_freed_attr.attr,
-	&zcache_qc_used_attr.attr,
-	&zcache_qc_max_used_attr.attr,
-	NULL,
-};
-
-static struct attribute_group qcache_attr_group = {
-	.attrs = qcache_attrs,
-	.name = "qcache",
-};
-
-#endif /* CONFIG_SYSFS */
-
-/*
- * zcache shims between cleancache ops and tmem
- */
-
-static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
-				uint32_t index, struct page *page)
-{
-	struct tmem_pool *pool;
-	int ret = -1;
-
-	BUG_ON(!irqs_disabled());
-	pool = zcache_get_pool_by_id(cli_id, pool_id);
-	if (unlikely(pool == NULL))
-		goto out;
-	if (!zcache_freeze && zcache_do_preload(pool) == 0) {
-		/* preload does preempt_disable on success */
-		ret = tmem_put(pool, oidp, index, (char *)(page),
-				PAGE_SIZE, 0, is_ephemeral(pool));
-		if (ret < 0) {
-			zcache_failed_eph_puts++;
-		}
-		zcache_put_pool(pool);
-		preempt_enable_no_resched();
-	} else {
-		zcache_put_to_flush++;
-		if (atomic_read(&pool->obj_count) > 0)
-			/* the put fails whether the flush succeeds or not */
-			(void)tmem_flush_page(pool, oidp, index);
-		zcache_put_pool(pool);
-	}
-out:
-	return ret;
-}
-
-static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
-				uint32_t index, struct page *page)
-{
-	struct tmem_pool *pool;
-	int ret = -1;
-	unsigned long flags;
-	size_t size = PAGE_SIZE;
-
-	local_irq_save(flags);
-	pool = zcache_get_pool_by_id(cli_id, pool_id);
-	if (likely(pool != NULL)) {
-		if (atomic_read(&pool->obj_count) > 0)
-			ret = tmem_get(pool, oidp, index, (char *)(page),
-					&size, 0, is_ephemeral(pool));
-		zcache_put_pool(pool);
-	}
-	local_irq_restore(flags);
-	return ret;
-}
-
-static int zcache_flush_page(int cli_id, int pool_id,
-				struct tmem_oid *oidp, uint32_t index)
-{
-	struct tmem_pool *pool;
-	int ret = -1;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	zcache_flush_total++;
-	pool = zcache_get_pool_by_id(cli_id, pool_id);
-	if (likely(pool != NULL)) {
-		if (atomic_read(&pool->obj_count) > 0)
-			ret = tmem_flush_page(pool, oidp, index);
-		zcache_put_pool(pool);
-	}
-	if (ret >= 0)
-		zcache_flush_found++;
-	local_irq_restore(flags);
-	return ret;
-}
-
-static int zcache_flush_object(int cli_id, int pool_id,
-				struct tmem_oid *oidp)
-{
-	struct tmem_pool *pool;
-	int ret = -1;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	zcache_flobj_total++;
-	pool = zcache_get_pool_by_id(cli_id, pool_id);
-	if (likely(pool != NULL)) {
-		if (atomic_read(&pool->obj_count) > 0)
-			ret = tmem_flush_object(pool, oidp);
-		zcache_put_pool(pool);
-	}
-	if (ret >= 0)
-		zcache_flobj_found++;
-	local_irq_restore(flags);
-	return ret;
-}
-
-static int zcache_destroy_pool(int cli_id, int pool_id)
-{
-	struct tmem_pool *pool = NULL;
-	struct zcache_client *cli = NULL;
-	int ret = -1;
-
-	if (pool_id < 0)
-		goto out;
-	if (cli_id == LOCAL_CLIENT)
-		cli = &zcache_host;
-	else if ((unsigned int)cli_id < MAX_CLIENTS)
-		cli = &zcache_clients[cli_id];
-	if (cli == NULL)
-		goto out;
-	atomic_inc(&cli->refcount);
-	pool = cli->tmem_pools[pool_id];
-	if (pool == NULL)
-		goto out;
-	cli->tmem_pools[pool_id] = NULL;
-	/* wait for pool activity on other cpus to quiesce */
-	while (atomic_read(&pool->refcount) != 0)
-		;
-	atomic_dec(&cli->refcount);
-	local_bh_disable();
-	ret = tmem_destroy_pool(pool);
-	local_bh_enable();
-	kfree(pool);
-	pr_info("qcache: destroyed pool id=%d, cli_id=%d\n",
-			pool_id, cli_id);
-out:
-	return ret;
-}
-
-static int zcache_new_pool(uint16_t cli_id, uint32_t flags)
-{
-	int poolid = -1;
-	struct tmem_pool *pool;
-	struct zcache_client *cli = NULL;
-
-	if (cli_id == LOCAL_CLIENT)
-		cli = &zcache_host;
-	else if ((unsigned int)cli_id < MAX_CLIENTS)
-		cli = &zcache_clients[cli_id];
-	if (cli == NULL)
-		goto out;
-	atomic_inc(&cli->refcount);
-	pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL);
-	if (pool == NULL) {
-		pr_info("qcache: pool creation failed: out of memory\n");
-		goto out;
-	}
-
-	for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++)
-		if (cli->tmem_pools[poolid] == NULL)
-			break;
-	if (poolid >= MAX_POOLS_PER_CLIENT) {
-		pr_info("qcache: pool creation failed: max exceeded\n");
-		kfree(pool);
-		poolid = -1;
-		goto out;
-	}
-	atomic_set(&pool->refcount, 0);
-	pool->client = cli;
-	pool->pool_id = poolid;
-	tmem_new_pool(pool, flags);
-	cli->tmem_pools[poolid] = pool;
-	pr_info("qcache: created %s tmem pool, id=%d, client=%d\n",
-		flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral",
-		poolid, cli_id);
-out:
-	if (cli != NULL)
-		atomic_dec(&cli->refcount);
-	return poolid;
-}
-
-/**********
- * Two kernel functionalities currently can be layered on top of tmem.
- * These are "cleancache" which is used as a second-chance cache for clean
- * page cache pages; and "frontswap" which is used for swap pages
- * to avoid writes to disk.  A generic "shim" is provided here for each
- * to translate in-kernel semantics to zcache semantics.
- */
-
-static void zcache_cleancache_put_page(int pool_id,
-					struct cleancache_filekey key,
-					pgoff_t index, struct page *page)
-{
-	u32 ind = (u32) index;
-	struct tmem_oid oid = *(struct tmem_oid *)&key;
-
-	if (likely(ind == index))
-		(void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page);
-}
-
-static int zcache_cleancache_get_page(int pool_id,
-					struct cleancache_filekey key,
-					pgoff_t index, struct page *page)
-{
-	u32 ind = (u32) index;
-	struct tmem_oid oid = *(struct tmem_oid *)&key;
-	int ret = -1;
-
-	if (likely(ind == index))
-		ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page);
-	return ret;
-}
-
-static void zcache_cleancache_flush_page(int pool_id,
-					struct cleancache_filekey key,
-					pgoff_t index)
-{
-	u32 ind = (u32) index;
-	struct tmem_oid oid = *(struct tmem_oid *)&key;
-
-	if (likely(ind == index))
-		(void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind);
-}
-
-static void zcache_cleancache_flush_inode(int pool_id,
-					struct cleancache_filekey key)
-{
-	struct tmem_oid oid = *(struct tmem_oid *)&key;
-
-	(void)zcache_flush_object(LOCAL_CLIENT, pool_id, &oid);
-}
-
-static void zcache_cleancache_flush_fs(int pool_id)
-{
-	if (pool_id >= 0)
-		(void)zcache_destroy_pool(LOCAL_CLIENT, pool_id);
-}
-
-static int zcache_cleancache_init_fs(size_t pagesize)
-{
-	BUG_ON(sizeof(struct cleancache_filekey) !=
-				sizeof(struct tmem_oid));
-	BUG_ON(pagesize != PAGE_SIZE);
-	return zcache_new_pool(LOCAL_CLIENT, 0);
-}
-
-static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
-{
-	/* shared pools are unsupported and map to private */
-	BUG_ON(sizeof(struct cleancache_filekey) !=
-				sizeof(struct tmem_oid));
-	BUG_ON(pagesize != PAGE_SIZE);
-	return zcache_new_pool(LOCAL_CLIENT, 0);
-}
-
-static struct cleancache_ops zcache_cleancache_ops = {
-	.put_page = zcache_cleancache_put_page,
-	.get_page = zcache_cleancache_get_page,
-	.invalidate_page = zcache_cleancache_flush_page,
-	.invalidate_inode = zcache_cleancache_flush_inode,
-	.invalidate_fs = zcache_cleancache_flush_fs,
-	.init_shared_fs = zcache_cleancache_init_shared_fs,
-	.init_fs = zcache_cleancache_init_fs
-};
-
-struct cleancache_ops zcache_cleancache_register_ops(void)
-{
-	struct cleancache_ops old_ops =
-		cleancache_register_ops(&zcache_cleancache_ops);
-
-	return old_ops;
-}
-
-static int __init qcache_init(void)
-{
-	int ret = 0;
-	struct qcache_info *qc = &qcache_info;
-	struct fmem_data *fdp;
-	int bitmap_size;
-	unsigned int cpu;
-	struct cleancache_ops old_ops;
-
-#ifdef CONFIG_SYSFS
-	ret = sysfs_create_group(mm_kobj, &qcache_attr_group);
-	if (ret) {
-		pr_err("qcache: can't create sysfs\n");
-		goto out;
-	}
-#endif /* CONFIG_SYSFS */
-
-	fdp = fmem_get_info();
-	qc->addr = fdp->virt;
-	qc->pages = fdp->size >> PAGE_SHIFT;
-	if (!qc->pages)
-		goto out;
-
-	tmem_register_hostops(&zcache_hostops);
-	tmem_register_pamops(&zcache_pamops);
-	for_each_online_cpu(cpu) {
-		per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages(
-			GFP_KERNEL | __GFP_REPEAT,
-			LZO_DSTMEM_PAGE_ORDER),
-		per_cpu(zcache_workmem, cpu) =
-			kzalloc(LZO1X_MEM_COMPRESS,
-				GFP_KERNEL | __GFP_REPEAT);
-	}
-	zcache_objnode_cache = kmem_cache_create("zcache_objnode",
-				sizeof(struct tmem_objnode), 0, 0, NULL);
-	zcache_obj_cache = kmem_cache_create("zcache_obj",
-				sizeof(struct tmem_obj), 0, 0, NULL);
-	ret = zcache_new_client(LOCAL_CLIENT);
-	if (ret) {
-		pr_err("qcache: can't create client\n");
-		goto out;
-	}
-
-	zbud_init();
-	old_ops = zcache_cleancache_register_ops();
-	pr_info("qcache: cleancache enabled using kernel "
-		"transcendent memory and compression buddies\n");
-	if (old_ops.init_fs != NULL)
-		pr_warning("qcache: cleancache_ops overridden");
-
-
-	bitmap_size = BITS_TO_LONGS(qc->pages) * sizeof(long);
-
-	qc->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!qc->bitmap) {
-		pr_info("can't allocate qcache bitmap!\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-	spin_lock_init(&qc->lock);
-
-	fmem_set_state(FMEM_T_STATE);
-
-out:
-	return ret;
-}
-
-module_init(qcache_init)
diff --git a/drivers/staging/qcache/tmem.c b/drivers/staging/qcache/tmem.c
deleted file mode 100644
index 40f2246..0000000
--- a/drivers/staging/qcache/tmem.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * In-kernel transcendent memory (generic implementation)
- *
- * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp.
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
- *
- * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented
- * "handles" (triples containing a pool id, and object id, and an index), to
- * pages in a page-accessible memory (PAM).  Tmem references the PAM pages via
- * an abstract "pampd" (PAM page-descriptor), which can be operated on by a
- * set of functions (pamops).  Each pampd contains some representation of
- * PAGE_SIZE bytes worth of data. Tmem must support potentially millions of
- * pages and must be able to insert, find, and delete these pages at a
- * potential frequency of thousands per second concurrently across many CPUs,
- * (and, if used with KVM, across many vcpus across many guests).
- * Tmem is tracked with a hierarchy of data structures, organized by
- * the elements in a handle-tuple: pool_id, object_id, and page index.
- * One or more "clients" (e.g. guests) each provide one or more tmem_pools.
- * Each pool, contains a hash table of rb_trees of tmem_objs.  Each
- * tmem_obj contains a radix-tree-like tree of pointers, with intermediate
- * nodes called tmem_objnodes.  Each leaf pointer in this tree points to
- * a pampd, which is accessible only through a small set of callbacks
- * registered by the PAM implementation (see tmem_register_pamops). Tmem
- * does all memory allocation via a set of callbacks registered by the tmem
- * host implementation (e.g. see tmem_register_hostops).
- */
-
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-
-#include "tmem.h"
-
-/* data structure sentinels used for debugging... see tmem.h */
-#define POOL_SENTINEL 0x87658765
-#define OBJ_SENTINEL 0x12345678
-#define OBJNODE_SENTINEL 0xfedcba09
-
-static bool tmem_enabled;
-
-static void lock_tmem_state(void)
-{
-	lock_fmem_state();
-}
-
-static void unlock_tmem_state(void)
-{
-	unlock_fmem_state();
-}
-
-/*
- * A tmem host implementation must use this function to register callbacks
- * for memory allocation.
- */
-static struct tmem_hostops tmem_hostops;
-
-static void tmem_objnode_tree_init(void);
-
-void tmem_register_hostops(struct tmem_hostops *m)
-{
-	tmem_objnode_tree_init();
-	tmem_hostops = *m;
-}
-
-/*
- * A tmem host implementation must use this function to register
- * callbacks for a page-accessible memory (PAM) implementation
- */
-static struct tmem_pamops tmem_pamops;
-
-void tmem_register_pamops(struct tmem_pamops *m)
-{
-	tmem_pamops = *m;
-}
-
-/*
- * Oid's are potentially very sparse and tmem_objs may have an indeterminately
- * short life, being added and deleted at a relatively high frequency.
- * So an rb_tree is an ideal data structure to manage tmem_objs.  But because
- * of the potentially huge number of tmem_objs, each pool manages a hashtable
- * of rb_trees to reduce search, insert, delete, and rebalancing time.
- * Each hashbucket also has a lock to manage concurrent access.
- *
- * The following routines manage tmem_objs.  When any tmem_obj is accessed,
- * the hashbucket lock must be held.
- */
-
-/* searches for object==oid in pool, returns locked object if found */
-static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb,
-					struct tmem_oid *oidp)
-{
-	struct rb_node *rbnode;
-	struct tmem_obj *obj;
-
-	rbnode = hb->obj_rb_root.rb_node;
-	while (rbnode) {
-		BUG_ON(RB_EMPTY_NODE(rbnode));
-		obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node);
-		switch (tmem_oid_compare(oidp, &obj->oid)) {
-		case 0: /* equal */
-			goto out;
-		case -1:
-			rbnode = rbnode->rb_left;
-			break;
-		case 1:
-			rbnode = rbnode->rb_right;
-			break;
-		}
-	}
-	obj = NULL;
-out:
-	return obj;
-}
-
-static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *);
-
-/* free an object that has no more pampds in it */
-static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb)
-{
-	struct tmem_pool *pool;
-
-	BUG_ON(obj == NULL);
-	ASSERT_SENTINEL(obj, OBJ);
-	BUG_ON(obj->pampd_count > 0);
-	pool = obj->pool;
-	BUG_ON(pool == NULL);
-	if (obj->objnode_tree_root != NULL) /* may be "stump" with no leaves */
-		tmem_pampd_destroy_all_in_obj(obj);
-	BUG_ON(obj->objnode_tree_root != NULL);
-	BUG_ON((long)obj->objnode_count != 0);
-	atomic_dec(&pool->obj_count);
-	BUG_ON(atomic_read(&pool->obj_count) < 0);
-	INVERT_SENTINEL(obj, OBJ);
-	obj->pool = NULL;
-	tmem_oid_set_invalid(&obj->oid);
-	rb_erase(&obj->rb_tree_node, &hb->obj_rb_root);
-}
-
-/*
- * initialize, and insert an tmem_object_root (called only if find failed)
- */
-static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb,
-					struct tmem_pool *pool,
-					struct tmem_oid *oidp)
-{
-	struct rb_root *root = &hb->obj_rb_root;
-	struct rb_node **new = &(root->rb_node), *parent = NULL;
-	struct tmem_obj *this;
-
-	BUG_ON(pool == NULL);
-	atomic_inc(&pool->obj_count);
-	obj->objnode_tree_height = 0;
-	obj->objnode_tree_root = NULL;
-	obj->pool = pool;
-	obj->oid = *oidp;
-	obj->objnode_count = 0;
-	obj->pampd_count = 0;
-	(*tmem_pamops.new_obj)(obj);
-	SET_SENTINEL(obj, OBJ);
-	while (*new) {
-		BUG_ON(RB_EMPTY_NODE(*new));
-		this = rb_entry(*new, struct tmem_obj, rb_tree_node);
-		parent = *new;
-		switch (tmem_oid_compare(oidp, &this->oid)) {
-		case 0:
-			BUG(); /* already present; should never happen! */
-			break;
-		case -1:
-			new = &(*new)->rb_left;
-			break;
-		case 1:
-			new = &(*new)->rb_right;
-			break;
-		}
-	}
-	rb_link_node(&obj->rb_tree_node, parent, new);
-	rb_insert_color(&obj->rb_tree_node, root);
-}
-
-/*
- * Tmem is managed as a set of tmem_pools with certain attributes, such as
- * "ephemeral" vs "persistent".  These attributes apply to all tmem_objs
- * and all pampds that belong to a tmem_pool.  A tmem_pool is created
- * or deleted relatively rarely (for example, when a filesystem is
- * mounted or unmounted.
- */
-
-/* flush all data from a pool and, optionally, free it */
-static void tmem_pool_flush(struct tmem_pool *pool, bool destroy)
-{
-	struct rb_node *rbnode;
-	struct tmem_obj *obj;
-	struct tmem_hashbucket *hb = &pool->hashbucket[0];
-	int i;
-
-	BUG_ON(pool == NULL);
-	for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) {
-		spin_lock(&hb->lock);
-		rbnode = rb_first(&hb->obj_rb_root);
-		while (rbnode != NULL) {
-			obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node);
-			rbnode = rb_next(rbnode);
-			tmem_pampd_destroy_all_in_obj(obj);
-			tmem_obj_free(obj, hb);
-			(*tmem_hostops.obj_free)(obj, pool);
-		}
-		spin_unlock(&hb->lock);
-	}
-	if (destroy)
-		list_del(&pool->pool_list);
-}
-
-/*
- * A tmem_obj contains a radix-tree-like tree in which the intermediate
- * nodes are called tmem_objnodes.  (The kernel lib/radix-tree.c implementation
- * is very specialized and tuned for specific uses and is not particularly
- * suited for use from this code, though some code from the core algorithms has
- * been reused, thus the copyright notices below).  Each tmem_objnode contains
- * a set of pointers which point to either a set of intermediate tmem_objnodes
- * or a set of of pampds.
- *
- * Portions Copyright (C) 2001 Momchil Velikov
- * Portions Copyright (C) 2001 Christoph Hellwig
- * Portions Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com>
- */
-
-struct tmem_objnode_tree_path {
-	struct tmem_objnode *objnode;
-	int offset;
-};
-
-/* objnode height_to_maxindex translation */
-static unsigned long tmem_objnode_tree_h2max[OBJNODE_TREE_MAX_PATH + 1];
-
-static void tmem_objnode_tree_init(void)
-{
-	unsigned int ht, tmp;
-
-	for (ht = 0; ht < ARRAY_SIZE(tmem_objnode_tree_h2max); ht++) {
-		tmp = ht * OBJNODE_TREE_MAP_SHIFT;
-		if (tmp >= OBJNODE_TREE_INDEX_BITS)
-			tmem_objnode_tree_h2max[ht] = ~0UL;
-		else
-			tmem_objnode_tree_h2max[ht] =
-			    (~0UL >> (OBJNODE_TREE_INDEX_BITS - tmp - 1)) >> 1;
-	}
-}
-
-static struct tmem_objnode *tmem_objnode_alloc(struct tmem_obj *obj)
-{
-	struct tmem_objnode *objnode;
-
-	ASSERT_SENTINEL(obj, OBJ);
-	BUG_ON(obj->pool == NULL);
-	ASSERT_SENTINEL(obj->pool, POOL);
-	objnode = (*tmem_hostops.objnode_alloc)(obj->pool);
-	if (unlikely(objnode == NULL))
-		goto out;
-	objnode->obj = obj;
-	SET_SENTINEL(objnode, OBJNODE);
-	memset(&objnode->slots, 0, sizeof(objnode->slots));
-	objnode->slots_in_use = 0;
-	obj->objnode_count++;
-out:
-	return objnode;
-}
-
-static void tmem_objnode_free(struct tmem_objnode *objnode)
-{
-	struct tmem_pool *pool;
-	int i;
-
-	BUG_ON(objnode == NULL);
-	for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++)
-		BUG_ON(objnode->slots[i] != NULL);
-	ASSERT_SENTINEL(objnode, OBJNODE);
-	INVERT_SENTINEL(objnode, OBJNODE);
-	BUG_ON(objnode->obj == NULL);
-	ASSERT_SENTINEL(objnode->obj, OBJ);
-	pool = objnode->obj->pool;
-	BUG_ON(pool == NULL);
-	ASSERT_SENTINEL(pool, POOL);
-	objnode->obj->objnode_count--;
-	objnode->obj = NULL;
-	(*tmem_hostops.objnode_free)(objnode, pool);
-}
-
-/*
- * lookup index in object and return associated pampd (or NULL if not found)
- */
-static void **__tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
-{
-	unsigned int height, shift;
-	struct tmem_objnode **slot = NULL;
-
-	BUG_ON(obj == NULL);
-	ASSERT_SENTINEL(obj, OBJ);
-	BUG_ON(obj->pool == NULL);
-	ASSERT_SENTINEL(obj->pool, POOL);
-
-	height = obj->objnode_tree_height;
-	if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height])
-		goto out;
-	if (height == 0 && obj->objnode_tree_root) {
-		slot = &obj->objnode_tree_root;
-		goto out;
-	}
-	shift = (height-1) * OBJNODE_TREE_MAP_SHIFT;
-	slot = &obj->objnode_tree_root;
-	while (height > 0) {
-		if (*slot == NULL)
-			goto out;
-		slot = (struct tmem_objnode **)
-			((*slot)->slots +
-			 ((index >> shift) & OBJNODE_TREE_MAP_MASK));
-		shift -= OBJNODE_TREE_MAP_SHIFT;
-		height--;
-	}
-out:
-	return slot != NULL ? (void **)slot : NULL;
-}
-
-static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
-{
-	struct tmem_objnode **slot;
-
-	slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index);
-	return slot != NULL ? *slot : NULL;
-}
-
-static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index,
-					void *new_pampd)
-{
-	struct tmem_objnode **slot;
-	void *ret = NULL;
-
-	slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index);
-	if ((slot != NULL) && (*slot != NULL)) {
-		void *old_pampd = *(void **)slot;
-		*(void **)slot = new_pampd;
-		(*tmem_pamops.free)(old_pampd, obj->pool, NULL, 0);
-		ret = new_pampd;
-	}
-	return ret;
-}
-
-static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index,
-					void *pampd)
-{
-	int ret = 0;
-	struct tmem_objnode *objnode = NULL, *newnode, *slot;
-	unsigned int height, shift;
-	int offset = 0;
-
-	/* if necessary, extend the tree to be higher  */
-	if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) {
-		height = obj->objnode_tree_height + 1;
-		if (index > tmem_objnode_tree_h2max[height])
-			while (index > tmem_objnode_tree_h2max[height])
-				height++;
-		if (obj->objnode_tree_root == NULL) {
-			obj->objnode_tree_height = height;
-			goto insert;
-		}
-		do {
-			newnode = tmem_objnode_alloc(obj);
-			if (!newnode) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			newnode->slots[0] = obj->objnode_tree_root;
-			newnode->slots_in_use = 1;
-			obj->objnode_tree_root = newnode;
-			obj->objnode_tree_height++;
-		} while (height > obj->objnode_tree_height);
-	}
-insert:
-	slot = obj->objnode_tree_root;
-	height = obj->objnode_tree_height;
-	shift = (height-1) * OBJNODE_TREE_MAP_SHIFT;
-	while (height > 0) {
-		if (slot == NULL) {
-			/* add a child objnode.  */
-			slot = tmem_objnode_alloc(obj);
-			if (!slot) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			if (objnode) {
-
-				objnode->slots[offset] = slot;
-				objnode->slots_in_use++;
-			} else
-				obj->objnode_tree_root = slot;
-		}
-		/* go down a level */
-		offset = (index >> shift) & OBJNODE_TREE_MAP_MASK;
-		objnode = slot;
-		slot = objnode->slots[offset];
-		shift -= OBJNODE_TREE_MAP_SHIFT;
-		height--;
-	}
-	BUG_ON(slot != NULL);
-	if (objnode) {
-		objnode->slots_in_use++;
-		objnode->slots[offset] = pampd;
-	} else
-		obj->objnode_tree_root = pampd;
-	obj->pampd_count++;
-out:
-	return ret;
-}
-
-static void *tmem_pampd_delete_from_obj(struct tmem_obj *obj, uint32_t index)
-{
-	struct tmem_objnode_tree_path path[OBJNODE_TREE_MAX_PATH + 1];
-	struct tmem_objnode_tree_path *pathp = path;
-	struct tmem_objnode *slot = NULL;
-	unsigned int height, shift;
-	int offset;
-
-	BUG_ON(obj == NULL);
-	ASSERT_SENTINEL(obj, OBJ);
-	BUG_ON(obj->pool == NULL);
-	ASSERT_SENTINEL(obj->pool, POOL);
-	height = obj->objnode_tree_height;
-	if (index > tmem_objnode_tree_h2max[height])
-		goto out;
-	slot = obj->objnode_tree_root;
-	if (height == 0 && obj->objnode_tree_root) {
-		obj->objnode_tree_root = NULL;
-		goto out;
-	}
-	shift = (height - 1) * OBJNODE_TREE_MAP_SHIFT;
-	pathp->objnode = NULL;
-	do {
-		if (slot == NULL)
-			goto out;
-		pathp++;
-		offset = (index >> shift) & OBJNODE_TREE_MAP_MASK;
-		pathp->offset = offset;
-		pathp->objnode = slot;
-		slot = slot->slots[offset];
-		shift -= OBJNODE_TREE_MAP_SHIFT;
-		height--;
-	} while (height > 0);
-	if (slot == NULL)
-		goto out;
-	while (pathp->objnode) {
-		pathp->objnode->slots[pathp->offset] = NULL;
-		pathp->objnode->slots_in_use--;
-		if (pathp->objnode->slots_in_use) {
-			if (pathp->objnode == obj->objnode_tree_root) {
-				while (obj->objnode_tree_height > 0 &&
-				  obj->objnode_tree_root->slots_in_use == 1 &&
-				  obj->objnode_tree_root->slots[0]) {
-					struct tmem_objnode *to_free =
-						obj->objnode_tree_root;
-
-					obj->objnode_tree_root =
-							to_free->slots[0];
-					obj->objnode_tree_height--;
-					to_free->slots[0] = NULL;
-					to_free->slots_in_use = 0;
-					tmem_objnode_free(to_free);
-				}
-			}
-			goto out;
-		}
-		tmem_objnode_free(pathp->objnode); /* 0 slots used, free it */
-		pathp--;
-	}
-	obj->objnode_tree_height = 0;
-	obj->objnode_tree_root = NULL;
-
-out:
-	if (slot != NULL)
-		obj->pampd_count--;
-	BUG_ON(obj->pampd_count < 0);
-	return slot;
-}
-
-/* recursively walk the objnode_tree destroying pampds and objnodes */
-static void tmem_objnode_node_destroy(struct tmem_obj *obj,
-					struct tmem_objnode *objnode,
-					unsigned int ht)
-{
-	int i;
-
-	if (ht == 0)
-		return;
-	for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) {
-		if (objnode->slots[i]) {
-			if (ht == 1) {
-				obj->pampd_count--;
-				(*tmem_pamops.free)(objnode->slots[i],
-						obj->pool, NULL, 0);
-				objnode->slots[i] = NULL;
-				continue;
-			}
-			tmem_objnode_node_destroy(obj, objnode->slots[i], ht-1);
-			tmem_objnode_free(objnode->slots[i]);
-			objnode->slots[i] = NULL;
-		}
-	}
-}
-
-static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
-{
-	if (obj->objnode_tree_root == NULL)
-		return;
-	if (obj->objnode_tree_height == 0) {
-		obj->pampd_count--;
-		(*tmem_pamops.free)(obj->objnode_tree_root, obj->pool, NULL, 0);
-	} else {
-		tmem_objnode_node_destroy(obj, obj->objnode_tree_root,
-					obj->objnode_tree_height);
-		tmem_objnode_free(obj->objnode_tree_root);
-		obj->objnode_tree_height = 0;
-	}
-	obj->objnode_tree_root = NULL;
-	(*tmem_pamops.free_obj)(obj->pool, obj);
-}
-
-/*
- * Tmem is operated on by a set of well-defined actions:
- * "put", "get", "flush", "flush_object", "new pool" and "destroy pool".
- * (The tmem ABI allows for subpages and exchanges but these operations
- * are not included in this implementation.)
- *
- * These "tmem core" operations are implemented in the following functions.
- */
-
-/*
- * "Put" a page, e.g. copy a page from the kernel into newly allocated
- * PAM space (if such space is available).  Tmem_put is complicated by
- * a corner case: What if a page with matching handle already exists in
- * tmem?  To guarantee coherency, one of two actions is necessary: Either
- * the data for the page must be overwritten, or the page must be
- * "flushed" so that the data is not accessible to a subsequent "get".
- * Since these "duplicate puts" are relatively rare, this implementation
- * always flushes for simplicity.
- */
-int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
-		char *data, size_t size, bool raw, bool ephemeral)
-{
-	struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL;
-	void *pampd = NULL, *pampd_del = NULL;
-	int ret = -ENOMEM;
-	struct tmem_hashbucket *hb;
-
-	lock_tmem_state();
-	if (!tmem_enabled)
-		goto disabled;
-	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
-	spin_lock(&hb->lock);
-	obj = objfound = tmem_obj_find(hb, oidp);
-	if (obj != NULL) {
-		pampd = tmem_pampd_lookup_in_obj(objfound, index);
-		if (pampd != NULL) {
-			/* if found, is a dup put, flush the old one */
-			pampd_del = tmem_pampd_delete_from_obj(obj, index);
-			BUG_ON(pampd_del != pampd);
-			(*tmem_pamops.free)(pampd, pool, oidp, index);
-			if (obj->pampd_count == 0) {
-				objnew = obj;
-				objfound = NULL;
-			}
-			pampd = NULL;
-		}
-	} else {
-		obj = objnew = (*tmem_hostops.obj_alloc)(pool);
-		if (unlikely(obj == NULL)) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		tmem_obj_init(obj, hb, pool, oidp);
-	}
-	BUG_ON(obj == NULL);
-	BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound));
-	pampd = (*tmem_pamops.create)(data, size, raw, ephemeral,
-					obj->pool, &obj->oid, index);
-	if (unlikely(pampd == NULL))
-		goto free;
-	ret = tmem_pampd_add_to_obj(obj, index, pampd);
-	if (unlikely(ret == -ENOMEM))
-		/* may have partially built objnode tree ("stump") */
-		goto delete_and_free;
-	goto out;
-
-delete_and_free:
-	(void)tmem_pampd_delete_from_obj(obj, index);
-free:
-	if (pampd)
-		(*tmem_pamops.free)(pampd, pool, NULL, 0);
-	if (objnew) {
-		tmem_obj_free(objnew, hb);
-		(*tmem_hostops.obj_free)(objnew, pool);
-	}
-out:
-	spin_unlock(&hb->lock);
-disabled:
-	unlock_tmem_state();
-	return ret;
-}
-
-/*
- * "Get" a page, e.g. if one can be found, copy the tmem page with the
- * matching handle from PAM space to the kernel.  By tmem definition,
- * when a "get" is successful on an ephemeral page, the page is "flushed",
- * and when a "get" is successful on a persistent page, the page is retained
- * in tmem.  Note that to preserve
- * coherency, "get" can never be skipped if tmem contains the data.
- * That is, if a get is done with a certain handle and fails, any
- * subsequent "get" must also fail (unless of course there is a
- * "put" done with the same handle).
-
- */
-int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
-		char *data, size_t *size, bool raw, int get_and_free)
-{
-	struct tmem_obj *obj;
-	void *pampd;
-	bool ephemeral = is_ephemeral(pool);
-	int ret = -1;
-	struct tmem_hashbucket *hb;
-	bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral);
-	bool lock_held = false;
-
-	lock_tmem_state();
-	if (!tmem_enabled)
-		goto disabled;
-	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
-	spin_lock(&hb->lock);
-	lock_held = true;
-	obj = tmem_obj_find(hb, oidp);
-	if (obj == NULL)
-		goto out;
-	if (free)
-		pampd = tmem_pampd_delete_from_obj(obj, index);
-	else
-		pampd = tmem_pampd_lookup_in_obj(obj, index);
-	if (pampd == NULL)
-		goto out;
-	if (free) {
-		if (obj->pampd_count == 0) {
-			tmem_obj_free(obj, hb);
-			(*tmem_hostops.obj_free)(obj, pool);
-			obj = NULL;
-		}
-	}
-	if (tmem_pamops.is_remote(pampd)) {
-		lock_held = false;
-		spin_unlock(&hb->lock);
-	}
-	if (free)
-		ret = (*tmem_pamops.get_data_and_free)(
-				data, size, raw, pampd, pool, oidp, index);
-	else
-		ret = (*tmem_pamops.get_data)(
-				data, size, raw, pampd, pool, oidp, index);
-	if (ret < 0)
-		goto out;
-	ret = 0;
-out:
-	if (lock_held)
-		spin_unlock(&hb->lock);
-disabled:
-	unlock_tmem_state();
-	return ret;
-}
-
-/*
- * If a page in tmem matches the handle, "flush" this page from tmem such
- * that any subsequent "get" does not succeed (unless, of course, there
- * was another "put" with the same handle).
- */
-int tmem_flush_page(struct tmem_pool *pool,
-				struct tmem_oid *oidp, uint32_t index)
-{
-	struct tmem_obj *obj;
-	void *pampd;
-	int ret = -1;
-	struct tmem_hashbucket *hb;
-
-	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
-	spin_lock(&hb->lock);
-	obj = tmem_obj_find(hb, oidp);
-	if (obj == NULL)
-		goto out;
-	pampd = tmem_pampd_delete_from_obj(obj, index);
-	if (pampd == NULL)
-		goto out;
-	(*tmem_pamops.free)(pampd, pool, oidp, index);
-	if (obj->pampd_count == 0) {
-		tmem_obj_free(obj, hb);
-		(*tmem_hostops.obj_free)(obj, pool);
-	}
-	ret = 0;
-
-out:
-	spin_unlock(&hb->lock);
-	return ret;
-}
-
-/*
- * If a page in tmem matches the handle, replace the page so that any
- * subsequent "get" gets the new page.  Returns 0 if
- * there was a page to replace, else returns -1.
- */
-int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp,
-			uint32_t index, void *new_pampd)
-{
-	struct tmem_obj *obj;
-	int ret = -1;
-	struct tmem_hashbucket *hb;
-
-	lock_tmem_state();
-	if (!tmem_enabled)
-		goto disabled;
-	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
-	spin_lock(&hb->lock);
-	obj = tmem_obj_find(hb, oidp);
-	if (obj == NULL)
-		goto out;
-	new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd);
-	ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj);
-out:
-	spin_unlock(&hb->lock);
-disabled:
-	unlock_tmem_state();
-	return ret;
-}
-
-/*
- * "Flush" all pages in tmem matching this oid.
- */
-int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp)
-{
-	struct tmem_obj *obj;
-	struct tmem_hashbucket *hb;
-	int ret = -1;
-
-	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
-	spin_lock(&hb->lock);
-	obj = tmem_obj_find(hb, oidp);
-	if (obj == NULL)
-		goto out;
-	tmem_pampd_destroy_all_in_obj(obj);
-	tmem_obj_free(obj, hb);
-	(*tmem_hostops.obj_free)(obj, pool);
-	ret = 0;
-
-out:
-	spin_unlock(&hb->lock);
-	return ret;
-}
-
-/*
- * "Flush" all pages (and tmem_objs) from this tmem_pool and disable
- * all subsequent access to this tmem_pool.
- */
-int tmem_destroy_pool(struct tmem_pool *pool)
-{
-	int ret = -1;
-
-	if (pool == NULL)
-		goto out;
-	tmem_pool_flush(pool, 1);
-	ret = 0;
-out:
-	return ret;
-}
-
-int tmem_flush_pool(struct tmem_pool *pool)
-{
-	int ret = -1;
-
-	if (pool == NULL)
-		goto out;
-	tmem_pool_flush(pool, 0);
-	ret = 0;
-out:
-	return ret;
-}
-
-static LIST_HEAD(tmem_global_pool_list);
-
-/*
- * Create a new tmem_pool with the provided flag and return
- * a pool id provided by the tmem host implementation.
- */
-void tmem_new_pool(struct tmem_pool *pool, uint32_t flags)
-{
-	int persistent = flags & TMEM_POOL_PERSIST;
-	int shared = flags & TMEM_POOL_SHARED;
-	struct tmem_hashbucket *hb = &pool->hashbucket[0];
-	int i;
-
-	for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) {
-		hb->obj_rb_root = RB_ROOT;
-		spin_lock_init(&hb->lock);
-	}
-	INIT_LIST_HEAD(&pool->pool_list);
-	atomic_set(&pool->obj_count, 0);
-	SET_SENTINEL(pool, POOL);
-	list_add_tail(&pool->pool_list, &tmem_global_pool_list);
-	pool->persistent = persistent;
-	pool->shared = shared;
-}
-
-/* The following must be called with tmem state locked */
-static void tmem_cleanup(void)
-{
-	(*tmem_hostops.flush_all_obj)();
-}
-
-void tmem_enable(void)
-{
-	pr_info("turning tmem on\n");
-	tmem_enabled = true;
-
-	(*tmem_hostops.control)(false);
-}
-
-void tmem_disable(void)
-{
-	pr_info("turning tmem off\n");
-	tmem_enabled = false;
-
-	tmem_cleanup();
-	(*tmem_hostops.control)(true);
-}
diff --git a/drivers/staging/qcache/tmem.h b/drivers/staging/qcache/tmem.h
deleted file mode 100644
index 359c201..0000000
--- a/drivers/staging/qcache/tmem.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * tmem.h
- *
- * Transcendent memory
- *
- * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp.
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _TMEM_H_
-#define _TMEM_H_
-
-#include <linux/types.h>
-#include <linux/highmem.h>
-#include <linux/hash.h>
-#include <linux/atomic.h>
-#include <linux/fmem.h>
-
-/*
- * These are pre-defined by the Xen<->Linux ABI
- */
-#define TMEM_PUT_PAGE			4
-#define TMEM_GET_PAGE			5
-#define TMEM_FLUSH_PAGE			6
-#define TMEM_FLUSH_OBJECT		7
-#define TMEM_POOL_PERSIST		1
-#define TMEM_POOL_SHARED		2
-#define TMEM_POOL_PRECOMPRESSED		4
-#define TMEM_POOL_PAGESIZE_SHIFT	4
-#define TMEM_POOL_PAGESIZE_MASK		0xf
-#define TMEM_POOL_RESERVED_BITS		0x00ffff00
-
-/*
- * sentinels have proven very useful for debugging but can be removed
- * or disabled before final merge.
- */
-#define SENTINELS
-#ifdef SENTINELS
-#define DECL_SENTINEL uint32_t sentinel;
-#define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL)
-#define INVERT_SENTINEL(_x, _y) (_x->sentinel = ~_y##_SENTINEL)
-#define ASSERT_SENTINEL(_x, _y) WARN_ON(_x->sentinel != _y##_SENTINEL)
-#define ASSERT_INVERTED_SENTINEL(_x, _y) WARN_ON(_x->sentinel != ~_y##_SENTINEL)
-#else
-#define DECL_SENTINEL
-#define SET_SENTINEL(_x, _y) do { } while (0)
-#define INVERT_SENTINEL(_x, _y) do { } while (0)
-#define ASSERT_SENTINEL(_x, _y) do { } while (0)
-#define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0)
-#endif
-
-/*
- * A pool is the highest-level data structure managed by tmem and
- * usually corresponds to a large independent set of pages such as
- * a filesystem.  Each pool has an id, and certain attributes and counters.
- * It also contains a set of hash buckets, each of which contains an rbtree
- * of objects and a lock to manage concurrency within the pool.
- */
-
-#define TMEM_HASH_BUCKET_BITS	8
-#define TMEM_HASH_BUCKETS	(1<<TMEM_HASH_BUCKET_BITS)
-
-struct tmem_hashbucket {
-	struct rb_root obj_rb_root;
-	spinlock_t lock;
-};
-
-struct tmem_pool {
-	void *client; /* "up" for some clients, avoids table lookup */
-	struct list_head pool_list;
-	uint32_t pool_id;
-	bool persistent;
-	bool shared;
-	atomic_t obj_count;
-	atomic_t refcount;
-	struct tmem_hashbucket hashbucket[TMEM_HASH_BUCKETS];
-	DECL_SENTINEL
-};
-
-#define is_persistent(_p)  (_p->persistent)
-#define is_ephemeral(_p)   (!(_p->persistent))
-
-/*
- * An object id ("oid") is large: 192-bits (to ensure, for example, files
- * in a modern filesystem can be uniquely identified).
- */
-
-struct tmem_oid {
-	uint64_t oid[3];
-};
-
-static inline void tmem_oid_set_invalid(struct tmem_oid *oidp)
-{
-	oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL;
-}
-
-static inline bool tmem_oid_valid(struct tmem_oid *oidp)
-{
-	return oidp->oid[0] != -1UL || oidp->oid[1] != -1UL ||
-		oidp->oid[2] != -1UL;
-}
-
-static inline int tmem_oid_compare(struct tmem_oid *left,
-					struct tmem_oid *right)
-{
-	int ret;
-
-	if (left->oid[2] == right->oid[2]) {
-		if (left->oid[1] == right->oid[1]) {
-			if (left->oid[0] == right->oid[0])
-				ret = 0;
-			else if (left->oid[0] < right->oid[0])
-				ret = -1;
-			else
-				return 1;
-		} else if (left->oid[1] < right->oid[1])
-			ret = -1;
-		else
-			ret = 1;
-	} else if (left->oid[2] < right->oid[2])
-		ret = -1;
-	else
-		ret = 1;
-	return ret;
-}
-
-static inline unsigned tmem_oid_hash(struct tmem_oid *oidp)
-{
-	return hash_long(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2],
-				TMEM_HASH_BUCKET_BITS);
-}
-
-/*
- * A tmem_obj contains an identifier (oid), pointers to the parent
- * pool and the rb_tree to which it belongs, counters, and an ordered
- * set of pampds, structured in a radix-tree-like tree.  The intermediate
- * nodes of the tree are called tmem_objnodes.
- */
-
-struct tmem_objnode;
-
-struct tmem_obj {
-	struct tmem_oid oid;
-	struct tmem_pool *pool;
-	struct rb_node rb_tree_node;
-	struct tmem_objnode *objnode_tree_root;
-	unsigned int objnode_tree_height;
-	unsigned long objnode_count;
-	long pampd_count;
-	void *extra; /* for private use by pampd implementation */
-	DECL_SENTINEL
-};
-
-#define OBJNODE_TREE_MAP_SHIFT 6
-#define OBJNODE_TREE_MAP_SIZE (1UL << OBJNODE_TREE_MAP_SHIFT)
-#define OBJNODE_TREE_MAP_MASK (OBJNODE_TREE_MAP_SIZE-1)
-#define OBJNODE_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long))
-#define OBJNODE_TREE_MAX_PATH \
-		(OBJNODE_TREE_INDEX_BITS/OBJNODE_TREE_MAP_SHIFT + 2)
-
-struct tmem_objnode {
-	struct tmem_obj *obj;
-	DECL_SENTINEL
-	void *slots[OBJNODE_TREE_MAP_SIZE];
-	unsigned int slots_in_use;
-};
-
-/* pampd abstract datatype methods provided by the PAM implementation */
-struct tmem_pamops {
-	void *(*create)(char *, size_t, bool, int,
-			struct tmem_pool *, struct tmem_oid *, uint32_t);
-	int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *,
-				struct tmem_oid *, uint32_t);
-	int (*get_data_and_free)(char *, size_t *, bool, void *,
-				struct tmem_pool *, struct tmem_oid *,
-				uint32_t);
-	void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t);
-	void (*free_obj)(struct tmem_pool *, struct tmem_obj *);
-	bool (*is_remote)(void *);
-	void (*new_obj)(struct tmem_obj *);
-	int (*replace_in_obj)(void *, struct tmem_obj *);
-};
-extern void tmem_register_pamops(struct tmem_pamops *m);
-
-/* memory allocation methods provided by the host implementation */
-struct tmem_hostops {
-	struct tmem_obj *(*obj_alloc)(struct tmem_pool *);
-	void (*obj_free)(struct tmem_obj *, struct tmem_pool *);
-	struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *);
-	void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *);
-	void (*flush_all_obj)(void);
-	void (*control)(bool);
-};
-extern void tmem_register_hostops(struct tmem_hostops *m);
-
-/* core tmem accessor functions */
-extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index,
-			char *, size_t, bool, bool);
-extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index,
-			char *, size_t *, bool, int);
-extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index,
-			void *);
-extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *,
-			uint32_t index);
-extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);
-extern int tmem_destroy_pool(struct tmem_pool *);
-extern int tmem_flush_pool(struct tmem_pool *);
-extern void tmem_new_pool(struct tmem_pool *, uint32_t);
-
-extern void tmem_enable(void);
-extern void tmem_disable(void);
-#endif /* _TMEM_H */
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index d1545dc..3794aa9 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -1187,8 +1187,11 @@
 			enable_powerdown = 1;
 
 		ch->local_state = SMUX_LCH_LOCAL_OPENED;
-		if (ch->remote_state == SMUX_LCH_REMOTE_OPENED)
+		if (ch->remote_state == SMUX_LCH_REMOTE_OPENED) {
 			schedule_notify(lcid, SMUX_CONNECTED, NULL);
+			if (!(list_empty(&ch->tx_queue)))
+				list_channel(ch);
+		}
 		ret = 0;
 	} else if (ch->remote_mode == SMUX_LCH_MODE_REMOTE_LOOPBACK) {
 		SMUX_DBG("smux: Remote loopback OPEN ACK received\n");
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 2600001..2487e3f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -34,6 +34,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/qpnp-misc.h>
 #include <linux/usb/msm_hsusb.h>
+#include <linux/usb/msm_ext_chg.h>
 #include <linux/regulator/consumer.h>
 #include <linux/power_supply.h>
 #include <linux/qpnp/qpnp-adc.h>
@@ -165,7 +166,7 @@
 struct dwc3_msm {
 	struct device *dev;
 	void __iomem *base;
-	u32 resource_size;
+	struct resource *io_res;
 	int dbm_num_eps;
 	u8 ep_num_mapping[DBM_MAX_EPS];
 	const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
@@ -1557,7 +1558,7 @@
 	case DWC3_DCP_CHARGER:		return "USB_DCP_CHARGER";
 	case DWC3_CDP_CHARGER:		return "USB_CDP_CHARGER";
 	case DWC3_PROPRIETARY_CHARGER:	return "USB_PROPRIETARY_CHARGER";
-	case DWC3_UNSUPPORTED_CHARGER:	return "INVALID_CHARGER";
+	case DWC3_FLOATED_CHARGER:	return "USB_FLOATED_CHARGER";
 	default:			return "UNKNOWN_CHARGER";
 	}
 }
@@ -1571,6 +1572,7 @@
 {
 	struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, chg_work.work);
 	bool is_dcd = false, tmout, vout;
+	static bool dcd;
 	unsigned long delay;
 
 	dev_dbg(mdwc->dev, "chg detection work\n");
@@ -1586,19 +1588,15 @@
 		is_dcd = dwc3_chg_check_dcd(mdwc);
 		tmout = ++mdwc->dcd_retries == DWC3_CHG_DCD_MAX_RETRIES;
 		if (is_dcd || tmout) {
+			if (is_dcd)
+				dcd = true;
+			else
+				dcd = false;
 			dwc3_chg_disable_dcd(mdwc);
+			usleep_range(1000, 1200);
 			if (dwc3_chg_det_check_linestate(mdwc)) {
-				dwc3_chg_enable_primary_det(mdwc);
-				usleep_range(1000, 1200);
-				vout = dwc3_chg_det_check_output(mdwc);
-				if (!vout)
-					mdwc->charger.chg_type =
-						DWC3_UNSUPPORTED_CHARGER;
-				else
-					mdwc->charger.chg_type =
+				mdwc->charger.chg_type =
 						DWC3_PROPRIETARY_CHARGER;
-				dwc3_msm_write_reg(mdwc->base,
-						CHARGING_DET_CTRL_REG, 0x0);
 				mdwc->chg_state = USB_CHG_STATE_DETECTED;
 				delay = 0;
 				break;
@@ -1617,7 +1615,15 @@
 			delay = DWC3_CHG_SECONDARY_DET_TIME;
 			mdwc->chg_state = USB_CHG_STATE_PRIMARY_DONE;
 		} else {
-			mdwc->charger.chg_type = DWC3_SDP_CHARGER;
+			/*
+			 * Detect floating charger only if propreitary
+			 * charger detection is enabled.
+			 */
+			if (!dcd && prop_chg_detect)
+				mdwc->charger.chg_type =
+						DWC3_FLOATED_CHARGER;
+			else
+				mdwc->charger.chg_type = DWC3_SDP_CHARGER;
 			mdwc->chg_state = USB_CHG_STATE_DETECTED;
 			delay = 0;
 		}
@@ -2270,8 +2276,11 @@
 			__func__, ret);
 
 		if (mdwc->pmic_id_irq) {
+			unsigned long flags;
+			local_irq_save(flags);
 			/* ID may have changed while IRQ disabled; update it */
 			mdwc->id_state = !!irq_read_line(mdwc->pmic_id_irq);
+			local_irq_restore(flags);
 			enable_irq(mdwc->pmic_id_irq);
 		}
 
@@ -2392,47 +2401,68 @@
 	return 0;
 }
 
-static ssize_t
-dwc3_msm_ext_chg_write(struct file *file, const char __user *ubuf,
-				size_t size, loff_t *pos)
+static long
+dwc3_msm_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct dwc3_msm *mdwc = context;
-	char kbuf[16];
+	struct msm_usb_chg_info info = {0};
+	int ret = 0, val;
 
-	memset(kbuf, 0x00, sizeof(kbuf));
-	if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, size)))
-		return -EFAULT;
+	switch (cmd) {
+	case MSM_USB_EXT_CHG_INFO:
+		info.chg_block_type = USB_CHG_BLOCK_QSCRATCH;
+		info.page_offset = (context->io_res->start +
+				QSCRATCH_REG_OFFSET) & ~PAGE_MASK;
+		/*
+		 * The charger block register address space is only
+		 * 512 bytes.  But mmap() works on PAGE granularity.
+		 */
+		info.length = PAGE_SIZE;
 
-	pr_debug("%s: buf = %s\n", __func__, kbuf);
-
-	if (!strncmp(kbuf, "enable", 6)) {
-		pr_info("%s: on\n", __func__);
-		if (mdwc->charger.chg_type == DWC3_DCP_CHARGER) {
-			pm_runtime_get_sync(mdwc->dev);
+		if (copy_to_user((void __user *)arg, &info, sizeof(info))) {
+			pr_err("%s: copy to user failed\n\n", __func__);
+			ret = -EFAULT;
+		}
+		break;
+	case MSM_USB_EXT_CHG_BLOCK_LPM:
+		if (get_user(val, (int __user *)arg)) {
+			pr_err("%s: get_user failed\n\n", __func__);
+			ret = -EFAULT;
+			break;
+		}
+		pr_debug("%s: LPM block request %d\n", __func__, val);
+		if (val) { /* block LPM */
+			if (mdwc->charger.chg_type == DWC3_DCP_CHARGER) {
+				pm_runtime_get_sync(mdwc->dev);
+			} else {
+				mdwc->ext_chg_active = false;
+				complete(&mdwc->ext_chg_wait);
+				ret = -ENODEV;
+			}
 		} else {
 			mdwc->ext_chg_active = false;
 			complete(&mdwc->ext_chg_wait);
-			return -ENODEV;
+			pm_runtime_put(mdwc->dev);
 		}
-	} else if (!strncmp(kbuf, "disable", 7)) {
-		pr_info("%s: off\n", __func__);
-		mdwc->ext_chg_active = false;
-		complete(&mdwc->ext_chg_wait);
-		pm_runtime_put(mdwc->dev);
-	} else {
-		return -EINVAL;
+		break;
+	default:
+		ret = -EINVAL;
 	}
 
-	return size;
+	return ret;
 }
 
 static int dwc3_msm_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
 {
+	struct dwc3_msm *mdwc = context;
 	unsigned long vsize = vma->vm_end - vma->vm_start;
 	int ret;
 
-	pr_debug("%s: size = %lu %x\n", __func__, vsize, (int) vma->vm_pgoff);
+	if (vma->vm_pgoff != 0 || vsize > PAGE_SIZE)
+		return -EINVAL;
 
+	vma->vm_pgoff = __phys_to_pfn(mdwc->io_res->start +
+				QSCRATCH_REG_OFFSET);
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 	ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
@@ -2457,7 +2487,7 @@
 static const struct file_operations dwc3_msm_ext_chg_fops = {
 	.owner = THIS_MODULE,
 	.open = dwc3_msm_ext_chg_open,
-	.write = dwc3_msm_ext_chg_write,
+	.unlocked_ioctl = dwc3_msm_ext_chg_ioctl,
 	.mmap = dwc3_msm_ext_chg_mmap,
 	.release = dwc3_msm_ext_chg_release,
 };
@@ -2791,7 +2821,7 @@
 		goto disable_hs_ldo;
 	}
 
-	msm->resource_size = resource_size(res);
+	msm->io_res = res; /* used to calculate chg block offset */
 
 	if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
 						&msm->hsphy_init_seq))
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 98c9b4c..1bc7757 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -726,8 +726,17 @@
 					phy->state = OTG_STATE_B_PERIPHERAL;
 					work = 1;
 					break;
-				case DWC3_UNSUPPORTED_CHARGER:
+				case DWC3_FLOATED_CHARGER:
 					dotg->charger_retry_count++;
+					/*
+					 * In case of floating charger, if
+					 * retry count equal to max retry count
+					 * notify PMIC about floating charger
+					 * and put Hw in low power mode. Else
+					 * perform charger detection again by
+					 * calling start_detection() with false
+					 * and then with true argument.
+					 */
 					if (dotg->charger_retry_count ==
 						max_chgr_retry_count) {
 						dwc3_otg_set_power(phy, 0);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index b00468e..28573a1 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -64,6 +64,7 @@
  *                      IDEV_CHG_MAX can be drawn irrespective of USB state.
  * DWC3_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific
  *                     voltages between 2.0-3.3v for identification.
+ * DWC3_FLOATED_CHARGER Non standard charger whose data lines are floating.
  */
 enum dwc3_chg_type {
 	DWC3_INVALID_CHARGER = 0,
@@ -71,7 +72,7 @@
 	DWC3_DCP_CHARGER,
 	DWC3_CDP_CHARGER,
 	DWC3_PROPRIETARY_CHARGER,
-	DWC3_UNSUPPORTED_CHARGER,
+	DWC3_FLOATED_CHARGER,
 };
 
 struct dwc3_charger {
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 46b5ce4..cc0c1e0 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -37,9 +37,12 @@
 
 	if (!pdata)
 		return;
-	else if (pdata->vendor == SYNOPSIS_DWC3_VENDOR &&
-			pdata->revision < 0x230A)
+
+	if (pdata->vendor == SYNOPSIS_DWC3_VENDOR && pdata->revision < 0x230A)
 		xhci->quirks |= XHCI_PORTSC_DELAY;
+
+	if (pdata->vendor == SYNOPSIS_DWC3_VENDOR && pdata->revision == 0x250A)
+		xhci->quirks |= XHCI_RESET_DELAY;
 }
 
 /* called during probe() after chip reset completes */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index df41b4f..ad09139 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4055,6 +4055,9 @@
 	retval = xhci_reset(xhci);
 	if (retval)
 		goto error;
+
+	if (xhci->quirks & XHCI_RESET_DELAY)
+		usleep_range(350, 1000);
 	xhci_dbg(xhci, "Reset complete\n");
 
 	temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index e47f46c..1ba51c2 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1497,6 +1497,14 @@
  * (16.66 ns x 5 = 84ns) ~100ns after writing to the PORTSC register.
  */
 #define XHCI_PORTSC_DELAY	(1 << 10)
+/*
+ * In Synopsis DWC3 controller, XHCI RESET takes some time complete. If PIPE
+ * RESET is not complete by the time USBCMD.RUN bit is set then HC fails to
+ * carry out SS transfers.
+ *
+ * The workaround is to give worst case pipe delay ~350us after resetting HC
+ */
+#define XHCI_RESET_DELAY	(1 << 11)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
 	/* There are two roothubs to keep track of bus suspend info for */
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 72c3c7d..eb65509 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -992,8 +992,8 @@
 	 * BC1.2 spec mandates PD to enable VDP_SRC when charging from DCP.
 	 * PHY retention and collapse can not happen with VDP_SRC enabled.
 	 */
-	if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend &&
-		!device_bus_suspend && !dcp) {
+	if (motg->caps & ALLOW_PHY_RETENTION && !device_bus_suspend && !dcp &&
+		 (!host_bus_suspend || motg->caps & ALLOW_HOST_PHY_RETENTION)) {
 		phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL) {
 			/* Enable PHY HV interrupts to wake MPM/Link */
@@ -1004,7 +1004,8 @@
 			else
 				phy_ctrl_val |= PHY_OTGSESSVLDHV_INTEN;
 		}
-
+		if (host_bus_suspend)
+			phy_ctrl_val |= PHY_CLAMP_DPDMSE_EN;
 		writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
 		motg->lpm_flags |= PHY_RETENTIONED;
 	}
@@ -1021,7 +1022,7 @@
 	}
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
-	if (!host_bus_suspend) {
+	if (!host_bus_suspend || (motg->caps & ALLOW_HOST_PHY_RETENTION)) {
 		if (!IS_ERR(motg->xo_clk)) {
 			clk_disable_unprepare(motg->xo_clk);
 			motg->lpm_flags |= XO_SHUTDOWN;
@@ -1062,12 +1063,17 @@
 		if (pdata->otg_control == OTG_PHY_CONTROL &&
 			pdata->mpm_otgsessvld_int)
 			msm_mpm_set_pin_wake(pdata->mpm_otgsessvld_int, 1);
+		if (host_bus_suspend && pdata->mpm_dpshv_int)
+			msm_mpm_set_pin_wake(pdata->mpm_dpshv_int, 1);
+		if (host_bus_suspend && pdata->mpm_dmshv_int)
+			msm_mpm_set_pin_wake(pdata->mpm_dmshv_int, 1);
 	}
 	if (bus)
 		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
 
 	msm_otg_bus_vote(motg, USB_NO_PERF_VOTE);
 
+	motg->host_bus_suspend = host_bus_suspend;
 	atomic_set(&motg->in_lpm, 1);
 	/* Enable ASYNC IRQ (if present) during LPM */
 	if (motg->async_irq)
@@ -1135,6 +1141,7 @@
 			/* Disable PHY HV interrupts */
 			phy_ctrl_val &=
 				~(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
+		phy_ctrl_val &= ~(PHY_CLAMP_DPDMSE_EN);
 		writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
 		motg->lpm_flags &= ~PHY_RETENTIONED;
 	}
@@ -1182,6 +1189,10 @@
 		if (pdata->otg_control == OTG_PHY_CONTROL &&
 			pdata->mpm_otgsessvld_int)
 			msm_mpm_set_pin_wake(pdata->mpm_otgsessvld_int, 0);
+		if (motg->host_bus_suspend && pdata->mpm_dpshv_int)
+			msm_mpm_set_pin_wake(pdata->mpm_dpshv_int, 0);
+		if (motg->host_bus_suspend && pdata->mpm_dmshv_int)
+			msm_mpm_set_pin_wake(pdata->mpm_dmshv_int, 0);
 	}
 	if (bus)
 		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
@@ -3866,6 +3877,10 @@
 	of_property_read_u32(node, "qcom,hsusb-log2-itc",
 				&pdata->log2_itc);
 
+	of_property_read_u32(node, "qcom,hsusb-otg-mpm-dpsehv-int",
+				&pdata->mpm_dpshv_int);
+	of_property_read_u32(node, "qcom,hsusb-otg-mpm-dmsehv-int",
+				&pdata->mpm_dmshv_int);
 	pdata->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
 	if (pdata->pmic_id_irq < 0)
 		pdata->pmic_id_irq = 0;
@@ -4167,6 +4182,11 @@
 	if (pdata->otg_control == OTG_PHY_CONTROL && pdata->mpm_otgsessvld_int)
 		msm_mpm_enable_pin(pdata->mpm_otgsessvld_int, 1);
 
+	if (pdata->mpm_dpshv_int)
+		msm_mpm_enable_pin(pdata->mpm_dpshv_int, 1);
+	if (pdata->mpm_dmshv_int)
+		msm_mpm_enable_pin(pdata->mpm_dmshv_int, 1);
+
 	phy->init = msm_otg_reset;
 	phy->set_power = msm_otg_set_power;
 	phy->set_suspend = msm_otg_set_suspend;
@@ -4230,6 +4250,9 @@
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
 			motg->caps = ALLOW_PHY_RETENTION |
 				ALLOW_PHY_REGULATORS_LPM;
+
+		if (motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int)
+			motg->caps |= ALLOW_HOST_PHY_RETENTION;
 	}
 
 	if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -4357,6 +4380,11 @@
 		motg->pdata->mpm_otgsessvld_int)
 		msm_mpm_enable_pin(motg->pdata->mpm_otgsessvld_int, 0);
 
+	if (motg->pdata->mpm_dpshv_int)
+		msm_mpm_enable_pin(motg->pdata->mpm_dpshv_int, 0);
+	if (motg->pdata->mpm_dmshv_int)
+		msm_mpm_enable_pin(motg->pdata->mpm_dmshv_int, 0);
+
 	/*
 	 * Put PHY in low power mode.
 	 */
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 91e70a7..bbf9b60 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -161,12 +161,19 @@
 {
 	int i = 0;
 	struct mdp3_hw_resource *mdata = (struct mdp3_hw_resource *)ptr;
-	u32 mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
+	u32 mdp_interrupt = 0;
 
+	spin_lock(&mdata->irq_lock);
+	if (!mdata->irq_mask) {
+		pr_err("spurious interrupt\n");
+		spin_unlock(&mdata->irq_lock);
+		return IRQ_HANDLED;
+	}
+
+	mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
 	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_interrupt);
 	pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
 
-	spin_lock(&mdata->irq_lock);
 	mdp_interrupt &= mdata->irq_mask;
 
 	while (mdp_interrupt && i < MDP3_MAX_INTR) {
@@ -183,7 +190,6 @@
 void mdp3_irq_enable(int type)
 {
 	unsigned long flag;
-	int irqEnabled = 0;
 
 	pr_debug("mdp3_irq_enable type=%d\n", type);
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
@@ -193,11 +199,10 @@
 		spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 		return;
 	}
-	irqEnabled = mdp3_res->irq_mask;
+
 	mdp3_res->irq_mask |= BIT(type);
 	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
-	if (!irqEnabled)
-		enable_irq(mdp3_res->irq);
+
 	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 }
 
@@ -220,8 +225,6 @@
 	if (mdp3_res->irq_ref_count[type] == 0) {
 		mdp3_res->irq_mask &= ~BIT(type);
 		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
-		if (!mdp3_res->irq_mask)
-			disable_irq_nosync(mdp3_res->irq);
 	}
 }
 
@@ -229,7 +232,7 @@
 {
 	unsigned long flag;
 
-	pr_debug("interrupt %d callback n", type);
+	pr_debug("interrupt %d callback\n", type);
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
 	if (cb)
 		mdp3_res->callbacks[type] = *cb;
@@ -240,6 +243,30 @@
 	return 0;
 }
 
+void mdp3_irq_register(void)
+{
+	unsigned long flag;
+
+	pr_debug("mdp3_irq_register\n");
+	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+	enable_irq(mdp3_res->irq);
+	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
+void mdp3_irq_deregister(void)
+{
+	unsigned long flag;
+
+	pr_debug("mdp3_irq_deregister\n");
+	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+	memset(mdp3_res->irq_ref_count, 0, sizeof(u32) * MDP3_MAX_INTR);
+	mdp3_res->irq_mask = 0;
+	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
+	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);
+	disable_irq_nosync(mdp3_res->irq);
+	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
 static int mdp3_bus_scale_register(void)
 {
 	int i;
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 1afae01..0482844 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -141,6 +141,8 @@
 void mdp3_irq_disable(int type);
 void mdp3_irq_disable_nosync(int type);
 int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb);
+void mdp3_irq_register(void);
+void mdp3_irq_deregister(void);
 int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
 int mdp3_clk_enable(int enable);
 int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index f43d1ed..a875f21 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -439,6 +439,8 @@
 		goto on_error;
 	}
 
+	mdp3_irq_register();
+
 	rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma);
 	if (rc) {
 		pr_err("dma init failed\n");
@@ -504,6 +506,8 @@
 	if (rc)
 		pr_err("fail to stop the MDP3 dma\n");
 
+	mdp3_irq_deregister();
+
 	pr_debug("mdp3_ctrl_off stop dsi panel and controller\n");
 	panel = mdp3_session->panel;
 	if (panel->event_handler)
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 48ffb72..afb2eb4 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -898,8 +898,8 @@
 	struct blit_req_list *req;
 	int i, rc;
 
-	req = mdp3_ppp_next_req(&ppp_stat->req_q);
 	mutex_lock(&ppp_stat->config_ppp_mutex);
+	req = mdp3_ppp_next_req(&ppp_stat->req_q);
 
 	mdp3_iommu_enable(MDP3_CLIENT_PPP);
 	mdp3_ppp_turnon(mfd, 1);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 078960b..840af17 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -89,6 +89,7 @@
 
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
+	u32 smp_mb_per_pipe;
 
 	u32 rot_block_size;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 56a4ac4..0a41ef8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1511,10 +1511,16 @@
 
 	rc = mdss_mdp_smp_setup(mdata, data[0], data[1]);
 
-	if (rc)
+	if (rc) {
 		pr_err("unable to setup smp data\n");
+		return rc;
+	}
 
-	return rc;
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-smp-mb-per-pipe", data);
+	mdata->smp_mb_per_pipe = (!rc ? data[0] : 0);
+
+	return 0;
 }
 
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 39952c9..950fd27 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -301,6 +301,11 @@
 	struct pp_sts_type pp_sts;
 };
 
+struct mdss_mdp_pipe_smp_map {
+	DECLARE_BITMAP(reserved, MDSS_MDP_SMP_MMB_BLOCKS);
+	DECLARE_BITMAP(allocated, MDSS_MDP_SMP_MMB_BLOCKS);
+};
+
 struct mdss_mdp_pipe {
 	u32 num;
 	u32 type;
@@ -337,8 +342,7 @@
 	struct mdp_overlay req_data;
 	u32 params_changed;
 
-	unsigned long smp[MAX_PLANES];
-	unsigned long smp_reserved[MAX_PLANES];
+	struct mdss_mdp_pipe_smp_map smp_map[MAX_PLANES];
 
 	struct mdss_mdp_data back_buf;
 	struct mdss_mdp_data front_buf;
@@ -567,6 +571,8 @@
 int mdss_panel_register_done(struct mdss_panel_data *pdata);
 int mdss_mdp_limited_lut_igc_config(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_calib_config(struct mdp_calib_config_data *cfg, u32 *copyback);
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+						u32 *copyback);
 
 int mdss_mdp_pipe_is_staged(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 8e5534d..c4c19b3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -496,7 +496,7 @@
 #define MDSS_MDP_REG_SMP_ALLOC_W0			0x00180
 #define MDSS_MDP_REG_SMP_ALLOC_R0			0x00230
 
-#define MDSS_MDP_SMP_MMB_BLOCKS			22
+#define MDSS_MDP_SMP_MMB_BLOCKS			44
 
 #define MDSS_MDP_LP_MISR_SEL			0x450
 #define MDSS_MDP_LP_MISR_CTRL_MDP		0x454
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index ab028e4..9b81633 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -573,7 +573,7 @@
 	mdss_mdp_ctl_write(ctl, 0, MDSS_MDP_LM_BORDER_COLOR);
 	off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
 
-	if (mdss_mdp_rev == MDSS_MDP_HW_REV_102)
+	if (mdss_mdp_rev >= MDSS_MDP_HW_REV_102)
 		mdss_v2_intf_off =  0xEC00;
 
 	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN -
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 953cbff..24b27b4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1241,7 +1241,7 @@
 
 static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
 {
-	struct mdss_mdp_data data;
+	struct mdss_mdp_data *buf;
 	struct mdss_mdp_pipe *pipe;
 	struct fb_info *fbi;
 	struct mdss_overlay_private *mdp5_data;
@@ -1271,8 +1271,6 @@
 		return;
 	}
 
-	memset(&data, 0, sizeof(data));
-
 	bpp = fbi->var.bits_per_pixel / 8;
 	offset = fbi->var.xoffset * bpp +
 		 fbi->var.yoffset * fbi->fix.line_length;
@@ -1289,18 +1287,6 @@
 		goto pan_display_error;
 	}
 
-	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
-		data.p[0].addr = fbi->fix.smem_start;
-
-	data.p[0].addr += offset;
-	data.p[0].len = fbi->fix.smem_len - offset;
-	data.num_planes = 1;
 
 	ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
 	if (ret) {
@@ -1312,13 +1298,23 @@
 		pr_err("unable to map base pipe\n");
 		goto pan_display_error;
 	}
-	ret = mdss_mdp_pipe_queue_data(pipe, &data);
-	mdss_mdp_pipe_unmap(pipe);
-	if (ret) {
-		pr_err("unable to queue data\n");
-		goto pan_display_error;
+
+	buf = &pipe->back_buf;
+	if (is_mdss_iommu_attached()) {
+		if (!mfd->iova) {
+			pr_err("mfd iova is zero\n");
+			goto pan_display_error;
+		}
+		buf->p[0].addr = mfd->iova;
+	} else {
+		buf->p[0].addr = fbi->fix.smem_start;
 	}
 
+	buf->p[0].addr += offset;
+	buf->p[0].len = fbi->fix.smem_len - offset;
+	buf->num_planes = 1;
+	mdss_mdp_pipe_unmap(pipe);
+
 	if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
 		ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
 						   MDSS_MDP_MIXER_MUX_RIGHT);
@@ -1330,12 +1326,8 @@
 			pr_err("unable to map right base pipe\n");
 			goto pan_display_error;
 		}
-		ret = mdss_mdp_pipe_queue_data(pipe, &data);
+		pipe->back_buf = *buf;
 		mdss_mdp_pipe_unmap(pipe);
-		if (ret) {
-			pr_err("unable to queue right data\n");
-			goto pan_display_error;
-		}
 	}
 	mutex_unlock(&mdp5_data->ov_lock);
 
@@ -1684,6 +1676,11 @@
 	case mdp_op_calib_mode:
 		ret = mdss_mdp_calib_mode(mfd, &mdp_pp.data.mdss_calib_cfg);
 		break;
+	case mdp_op_calib_buffer:
+		ret = mdss_mdp_calib_config_buffer(
+				(struct mdp_calib_config_buffer *)
+				 &mdp_pp.data.calib_buffer, &copyback);
+		break;
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL. %d = op\n",
 								mdp_pp.op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 137da66..d1e5e64 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -132,8 +132,8 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++) {
-		mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
-		mdss_mdp_smp_mmb_free(&pipe->smp[i], true);
+		mdss_mdp_smp_mmb_free(pipe->smp_map[i].reserved, false);
+		mdss_mdp_smp_mmb_free(pipe->smp_map[i].allocated, true);
 	}
 	mutex_unlock(&mdss_mdp_smp_lock);
 }
@@ -144,7 +144,7 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++)
-		mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+		mdss_mdp_smp_mmb_free(pipe->smp_map[i].reserved, false);
 	mutex_unlock(&mdss_mdp_smp_lock);
 }
 
@@ -193,13 +193,17 @@
 
 			if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
 				num_blks = roundup_pow_of_two(num_blks);
+
+			if (mdata->smp_mb_per_pipe &&
+				(num_blks > mdata->smp_mb_per_pipe) &&
+				!(pipe->flags & MDP_FLIP_LR))
+				num_blks = mdata->smp_mb_per_pipe;
 		}
 
 		pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
 				num_blks, pipe->num, i);
-		reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp[i],
-			&pipe->smp_reserved[i], num_blks);
-
+		reserved = mdss_mdp_smp_mmb_reserve(pipe->smp_map[i].allocated,
+			pipe->smp_map[i].reserved, num_blks);
 		if (reserved < num_blks)
 			break;
 	}
@@ -207,7 +211,8 @@
 	if (reserved < num_blks) {
 		pr_debug("insufficient MMB blocks\n");
 		for (; i >= 0; i--)
-			mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+			mdss_mdp_smp_mmb_free(pipe->smp_map[i].reserved,
+				false);
 		rc = -ENOMEM;
 	}
 	mutex_unlock(&mdss_mdp_smp_lock);
@@ -222,8 +227,10 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++) {
-		mdss_mdp_smp_mmb_amend(&pipe->smp[i], &pipe->smp_reserved[i]);
-		cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+		mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
+			pipe->smp_map[i].reserved);
+		cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
+			pipe->smp_map[i].allocated);
 	}
 	mdss_mdp_smp_set_wm_levels(pipe, cnt);
 	mutex_unlock(&mdss_mdp_smp_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 4dd9dcb..6cedd98 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3376,3 +3376,69 @@
 	mutex_unlock(&mdss_pp_mutex);
 	return 0;
 }
+
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+						u32 *copyback)
+{
+	int ret = -1;
+	int counter = cfg->size / (sizeof(uint32_t) * 2);
+	uint32_t *buff = NULL, *buff_org = NULL;
+	void *ptr;
+	int i = 0;
+
+	buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
+	if (buff == NULL) {
+		pr_err("Allocation failed");
+		return ret;
+	}
+
+	if (copy_from_user(buff, cfg->buffer, cfg->size)) {
+		kfree(buff);
+		pr_err("Copy failed");
+		return ret;
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	if (cfg->ops & MDP_PP_OPS_READ) {
+		for (i = 0 ; i < counter ; i++) {
+			if (is_valid_calib_addr((void *) *buff)) {
+				ret = 0;
+			} else {
+				ret = -1;
+				pr_err("Address validation failed");
+				break;
+			}
+
+			ptr = (void *)(((unsigned int) *buff) +
+					 (mdss_res->mdp_base));
+			buff++;
+			*buff = readl_relaxed(ptr);
+			buff++;
+		}
+		if (!ret)
+			ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
+		*copyback = 1;
+	} else if (cfg->ops & MDP_PP_OPS_WRITE) {
+		for (i = 0 ; i < counter ; i++) {
+			if (is_valid_calib_addr((void *) *buff)) {
+				ret = 0;
+			} else {
+				ret = -1;
+				pr_err("Address validation failed");
+				break;
+			}
+
+			ptr = (void *)(((unsigned int) *buff) +
+					 (mdss_res->mdp_base));
+			buff++;
+			writel_relaxed(*buff, ptr);
+			buff++;
+		}
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	kfree(buff_org);
+	return ret;
+}
diff --git a/include/linux/android_pmem.h b/include/linux/android_pmem.h
index cfca491..f338d15 100644
--- a/include/linux/android_pmem.h
+++ b/include/linux/android_pmem.h
@@ -151,10 +151,6 @@
 	 * indicates that this region should be mapped/unmaped as needed
 	 */
 	int map_on_demand;
-	/*
-	 * indicates this pmem may be reused via fmem
-	 */
-	int reusable;
 };
 
 int pmem_setup(struct android_pmem_platform_data *pdata,
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 3ae83d6..dd675f3 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -531,6 +531,9 @@
 /* Indicates whether TS insertion is supported */
 #define DMX_CAP_TS_INSERTION	0x20
 
+/* Indicates whether playback from secured input is supported */
+#define DMX_CAP_SECURED_INPUT_PLAYBACK	0x40
+
 	/* Number of decoders demux can output data to */
 	int num_decoders;
 
@@ -570,6 +573,9 @@
 	/* Max bitrate from single memory input. Mbit/sec */
 	int memory_input_max_bitrate;
 
+	/* Max number of supported cipher operations per PID */
+	int num_cipher_ops;
+
 	/* Max possible value of STC reported by demux, in 27MHz */
 	__u64 max_stc;
 
@@ -660,6 +666,15 @@
 struct dmx_buffer {
 	unsigned int size;
 	int handle;
+
+	/*
+	 * The following indication is relevant only when setting
+	 * DVR input buffer. It indicates whether the input buffer
+	 * being set is secured one or not. Secured (locked) buffers
+	 * are required for playback from secured input. In such case
+	 * write() syscall is not allowed.
+	 */
+	int is_protected;
 };
 
 struct dmx_decoder_buffers {
@@ -684,16 +699,41 @@
 
 struct dmx_secure_mode {
 	/*
-	 * Specifies whether secure mode should be set or not for the filter's
-	 * pid. Note that DMX_OUT_TSDEMUX_TAP filters can have more than 1 pid
+	 * Specifies whether the filter is secure or not.
+	 * Filter should be set as secured if the filter's data *may* include
+	 * encrypted data that would require decryption configured through
+	 * DMX_SET_CIPHER ioctl. The setting may be done while
+	 * filter is in idle state only.
 	 */
 	int is_secured;
+};
 
-	/* PID to associate with key ladder id */
+struct dmx_cipher_operation {
+	/* Indication whether the operation is encryption or decryption */
+	int encrypt;
+
+	/* The ID of the key used for decryption or encryption */
+	__u32 key_ladder_id;
+};
+
+#define DMX_MAX_CIPHER_OPERATIONS_COUNT	5
+struct dmx_cipher_operations {
+	/*
+	 * The PID to perform the cipher operations on.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have different
+	 * cipher operations.
+	 */
 	__u16 pid;
 
-	/* key ladder information to associate with the specified pid */
-	__u32 key_ladder_id;
+	/* Total number of operations */
+	__u8 operations_count;
+
+	/*
+	 * Cipher operation to perform on the given PID.
+	 * The operations are performed in the order they are given.
+	 */
+	struct dmx_cipher_operation operations[DMX_MAX_CIPHER_OPERATIONS_COUNT];
 };
 
 struct dmx_events_mask {
@@ -825,5 +865,7 @@
 #define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
 #define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
 #define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
+#define DMX_SET_CIPHER _IOW('o', 73, struct dmx_cipher_operations)
+
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/fmem.h b/include/linux/fmem.h
deleted file mode 100644
index cda4a0f..0000000
--- a/include/linux/fmem.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * Copyright (c) 2011-2012, 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 _FMEM_H_
-#define _FMEM_H_
-
-#include <linux/vmalloc.h>
-
-struct fmem_platform_data {
-	unsigned long phys;
-	unsigned long size;
-	unsigned long reserved_size_low;
-	unsigned long reserved_size_high;
-	unsigned long align;
-};
-
-struct fmem_data {
-	unsigned long phys;
-	void *virt;
-	struct vm_struct *area;
-	unsigned long size;
-	unsigned long reserved_size_low;
-	unsigned long reserved_size_high;
-};
-
-enum fmem_state {
-	FMEM_UNINITIALIZED = 0,
-	FMEM_C_STATE,
-	FMEM_T_STATE,
-	FMEM_O_STATE,
-};
-
-#ifdef CONFIG_QCACHE
-struct fmem_data *fmem_get_info(void);
-int fmem_set_state(enum fmem_state);
-void lock_fmem_state(void);
-void unlock_fmem_state(void);
-void *fmem_map_virtual_area(int cacheability);
-void fmem_unmap_virtual_area(void);
-#else
-static inline struct fmem_data *fmem_get_info(void) { return NULL; }
-static inline int fmem_set_state(enum fmem_state f) { return -ENODEV; }
-static inline void lock_fmem_state(void) { return; }
-static inline void unlock_fmem_state(void) { return; }
-static inline void *fmem_map_virtual_area(int cacheability) { return NULL; }
-static inline void fmem_unmap_virtual_area(void) { return; }
-#endif
-
-int request_fmem_c_region(void *unused);
-int release_fmem_c_region(void *unused);
-#endif
diff --git a/include/linux/input/mpu3050.h b/include/linux/input/mpu3050.h
index 61a2920..f87dfe3 100644
--- a/include/linux/input/mpu3050.h
+++ b/include/linux/input/mpu3050.h
@@ -25,6 +25,7 @@
 	int (*power_off)(void);
 
 	int gpio_int;
+	int gpio_en;
 	int gpio_fsync;
 };
 
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
index 412341a..bf76026 100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -276,5 +276,37 @@
 #define WCD9XXX_A_CDC_CLSH_V_PA_MIN_HPH			(0x331)
 #define WCD9XXX_A_CDC_CLSH_V_PA_MIN_HPH__POR				(0x00)
 
+#define WCD9XXX_A_CDC_RX1_B6_CTL			(0x2B5)
+#define WCD9XXX_A_CDC_RX1_B6_CTL__POR				(0x80)
+#define WCD9XXX_A_CDC_RX2_B6_CTL			(0x2BD)
+#define WCD9XXX_A_CDC_RX2_B6_CTL__POR				(0x80)
+#define WCD9XXX_A_RX_HPH_L_GAIN				(0x1AE)
+#define WCD9XXX_A_RX_HPH_L_GAIN__POR				(0x00)
+#define WCD9XXX_A_RX_HPH_R_GAIN				(0x1B4)
+#define WCD9XXX_A_RX_HPH_R_GAIN__POR				(0x00)
+#define WCD9XXX_A_RX_HPH_CHOP_CTL			(0x1A5)
+#define WCD9XXX_A_RX_HPH_CHOP_CTL__POR				(0xB4)
+#define WCD9XXX_A_RX_HPH_L_TEST				(0x1AF)
+#define WCD9XXX_A_RX_HPH_L_TEST__POR				(0x00)
+#define WCD9XXX_A_RX_HPH_R_TEST				(0x1B5)
+#define WCD9XXX_A_RX_HPH_R_TEST__POR				(0x00)
+#define WCD9XXX_A_CDC_CLK_RX_B1_CTL			(0x30F)
+#define WCD9XXX_A_CDC_CLK_RX_B1_CTL__POR			(0x00)
+#define WCD9XXX_A_NCP_CLK				(0x193)
+#define WCD9XXX_A_NCP_CLK__POR					(0x94)
+#define WCD9XXX_A_RX_HPH_BIAS_WG_OCP			(0x1A9)
+#define WCD9XXX_A_RX_HPH_BIAS_WG_OCP__POR			(0x2A)
+#define WCD9XXX_A_RX_HPH_CNP_WG_CTL			(0x1AC)
+#define WCD9XXX_A_RX_HPH_CNP_WG_CTL__POR			(0xDE)
+#define WCD9XXX_A_CDC_CONN_RX2_B1_CTL			(0x383)
+#define WCD9XXX_A_CDC_CONN_RX2_B1_CTL__POR			(0x00)
+#define WCD9XXX_A_CDC_PA_RAMP_B1_CTL			(0x361)
+#define WCD9XXX_A_CDC_PA_RAMP_B1_CTL__POR			(0x00)
+#define WCD9XXX_A_CDC_PA_RAMP_B2_CTL			(0x362)
+#define WCD9XXX_A_CDC_PA_RAMP_B2_CTL__POR			(0x00)
+#define WCD9XXX_A_CDC_PA_RAMP_B3_CTL			(0x363)
+#define WCD9XXX_A_CDC_PA_RAMP_B3_CTL__POR			(0x00)
+#define WCD9XXX_A_CDC_PA_RAMP_B4_CTL			(0x364)
+#define WCD9XXX_A_CDC_PA_RAMP_B4_CTL__POR			(0x00)
 
 #endif
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index f548721..e3ff5db 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -99,8 +99,8 @@
  */
 
 	unsigned int		cmd_timeout_ms;	/* in milliseconds */
-	/* Set this flag only for blocking bkops request */
-	bool			bkops_busy;
+	/* Set this flag only for commands which can be HPIed */
+	bool			ignore_timeout;
 
 	struct mmc_data		*data;		/* data segment associated with cmd */
 	struct mmc_request	*mrq;		/* associated request */
@@ -162,6 +162,8 @@
 extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
 			bool);
 extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
+extern int mmc_switch_ignore_timeout(struct mmc_card *, u8, u8, u8,
+				     unsigned int);
 extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
 
 #define MMC_ERASE_ARG		0x00000000
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 20b7317..6a8633b 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -97,7 +97,6 @@
 #define ION_PIL1_HEAP_NAME  "pil_1"
 #define ION_PIL2_HEAP_NAME  "pil_2"
 #define ION_QSECOM_HEAP_NAME	"qsecom"
-#define ION_FMEM_HEAP_NAME	"fmem"
 
 #define ION_SET_CACHED(__cache)		(__cache | ION_FLAG_CACHED)
 #define ION_SET_UNCACHED(__cache)	(__cache & ~ION_FLAG_CACHED)
@@ -129,12 +128,7 @@
  * @secure_size:	Memory size for securing the heap.
  *			Note: This might be different from actual size
  *			of this heap in the case of a shared heap.
- * @reusable		Flag indicating whether this heap is reusable of not.
- *			(see FMEM)
- * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
- *			or not.
  * @fixed_position	If nonzero, position in the fixed area.
- * @virt_addr:		Virtual address used when using fmem.
  * @iommu_map_all:	Indicates whether we should map whole heap into IOMMU.
  * @iommu_2x_map_domain: Indicates the domain to use for overmapping.
  * @request_region:	function to be called when the number of allocations
@@ -153,13 +147,10 @@
 	unsigned int align;
 	ion_phys_addr_t secure_base; /* Base addr used when heap is shared */
 	size_t secure_size; /* Size used for securing heap when heap is shared*/
-	int reusable;
-	int mem_is_fmem;
 	int is_cma;
 	enum ion_fixed_position fixed_position;
 	int iommu_map_all;
 	int iommu_2x_map_domain;
-	void *virt_addr;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *(*setup_region)(void);
@@ -171,8 +162,6 @@
  * struct ion_co_heap_pdata - defines a carveout heap in the given platform
  * @adjacent_mem_id:	Id of heap that this heap must be adjacent to.
  * @align:		Alignment requirement for the memory
- * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
- *			or not.
  * @fixed_position	If nonzero, position in the fixed area.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
@@ -185,7 +174,6 @@
 struct ion_co_heap_pdata {
 	int adjacent_mem_id;
 	unsigned int align;
-	int mem_is_fmem;
 	enum ion_fixed_position fixed_position;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 18921a0..c3ff9de 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -606,6 +606,12 @@
 	uint32_t data;
 };
 
+struct mdp_calib_config_buffer {
+	uint32_t ops;
+	uint32_t size;
+	uint32_t *buffer;
+};
+
 #define MDSS_MAX_BL_BRIGHTNESS 255
 #define AD_BL_LIN_LEN (MDSS_MAX_BL_BRIGHTNESS + 1)
 
@@ -697,6 +703,7 @@
 	mdp_op_ad_cfg,
 	mdp_op_ad_input,
 	mdp_op_calib_mode,
+	mdp_op_calib_buffer,
 	mdp_op_max,
 };
 
@@ -724,6 +731,7 @@
 		struct mdss_ad_init_cfg ad_init_cfg;
 		struct mdss_calib_cfg mdss_calib_cfg;
 		struct mdss_ad_input ad_input;
+		struct mdp_calib_config_buffer calib_buffer;
 	} data;
 };
 
diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h
index eed27f4..be655e4 100644
--- a/include/linux/pageblock-flags.h
+++ b/include/linux/pageblock-flags.h
@@ -71,13 +71,13 @@
 #ifdef CONFIG_COMPACTION
 #define get_pageblock_skip(page) \
 			get_pageblock_flags_group(page, PB_migrate_skip,     \
-							PB_migrate_skip + 1)
+							PB_migrate_skip)
 #define clear_pageblock_skip(page) \
 			set_pageblock_flags_group(page, 0, PB_migrate_skip,  \
-							PB_migrate_skip + 1)
+							PB_migrate_skip)
 #define set_pageblock_skip(page) \
 			set_pageblock_flags_group(page, 1, PB_migrate_skip,  \
-							PB_migrate_skip + 1)
+							PB_migrate_skip)
 #endif /* CONFIG_COMPACTION */
 
 #define get_pageblock_flags(page) \
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 72474e1..9fd5ec5 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -29,12 +29,21 @@
  *	if for example some other pin is going to drive the signal connected
  *	to it for a while. Pins used for input are usually always high
  *	impedance.
+ * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
+ *	weakly drives the last value on a tristate bus, also known as a "bus
+ *	holder", "bus keeper" or "repeater". This allows another device on the
+ *	bus to change the value by driving the bus high or low and switching to
+ *	tristate. The argument is ignored.
  * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
  *	impedance to VDD). If the argument is != 0 pull-up is enabled,
  *	if it is 0, pull-up is disabled.
  * @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
  *	impedance to GROUND). If the argument is != 0 pull-down is enabled,
  *	if it is 0, pull-down is disabled.
+ * @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: the pin will be pulled up or down based
+ *	on embedded knowledge of the controller, like current mux function.
+ *	If the argument is != 0 pull up/down is enabled, if it is 0,
+ *	the pull is disabled.
  * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
  *	low, this is the most typical case and is typically achieved with two
  *	active transistors on the output. Sending this config will enabale
@@ -78,8 +87,10 @@
 enum pin_config_param {
 	PIN_CONFIG_BIAS_DISABLE,
 	PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
+	PIN_CONFIG_BIAS_BUS_HOLD,
 	PIN_CONFIG_BIAS_PULL_UP,
 	PIN_CONFIG_BIAS_PULL_DOWN,
+	PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
 	PIN_CONFIG_DRIVE_PUSH_PULL,
 	PIN_CONFIG_DRIVE_OPEN_DRAIN,
 	PIN_CONFIG_DRIVE_OPEN_SOURCE,
diff --git a/include/linux/test-iosched.h b/include/linux/test-iosched.h
index 89d3b30..5b05b7a 100644
--- a/include/linux/test-iosched.h
+++ b/include/linux/test-iosched.h
@@ -130,7 +130,7 @@
  * @check_test_result_fn: Test specific test result checking
  *			callback
  * @get_test_case_str_fn: Test specific function to get the test name
- * @test_duration:	A jiffies value saved for timing
+ * @test_duration:	A ktime value saved for timing
  *			calculations
  * @data:		Test specific private data
  * @test_byte_count:	Total number of bytes dispatched in
@@ -144,7 +144,7 @@
 	check_test_result_fn *check_test_result_fn;
 	post_test_fn *post_test_fn;
 	get_test_case_str_fn *get_test_case_str_fn;
-	unsigned long test_duration;
+	ktime_t test_duration;
 	get_rq_disk_fn *get_rq_disk_fn;
 	void *data;
 	unsigned long test_byte_count;
@@ -263,4 +263,6 @@
 void test_iosched_add_urgent_req(struct test_request *test_rq);
 
 int test_is_req_urgent(struct request *rq);
+
+void check_test_completion(void);
 #endif /* _LINUX_TEST_IOSCHED_H */
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index b607f35..087d163 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -5,6 +5,7 @@
 header-y += functionfs.h
 header-y += gadgetfs.h
 header-y += midi.h
+header-y += msm_ext_chg.h
 header-y += g_printer.h
 header-y += tmc.h
 header-y += video.h
diff --git a/include/linux/usb/msm_ext_chg.h b/include/linux/usb/msm_ext_chg.h
new file mode 100644
index 0000000..dcc786d
--- /dev/null
+++ b/include/linux/usb/msm_ext_chg.h
@@ -0,0 +1,31 @@
+#ifndef __LINUX_USB_MSM_EXT_CHG_H
+#define __LINUX_USB_MSM_EXT_CHG_H
+
+#include <linux/ioctl.h>
+
+#define USB_CHG_BLOCK_ULPI	1
+#define USB_CHG_BLOCK_QSCRATCH	2
+
+/**
+ * struct msm_usb_chg_info - MSM USB charger block details.
+ * @chg_block_type: The type of charger block. QSCRATCH/ULPI.
+ * @page_offset: USB charger register base may not be aligned to
+ *              PAGE_SIZE.  The kernel driver aligns the base
+ *              address and use it for memory mapping.  This
+ *              page_offset is used by user space to calaculate
+ *              the corret charger register base address.
+ * @length: The length of the charger register address space.
+ */
+struct msm_usb_chg_info {
+	uint32_t chg_block_type;
+	off_t page_offset;
+	size_t length;
+};
+
+/* Get the MSM USB charger block information */
+#define MSM_USB_EXT_CHG_INFO _IOW('M', 0, struct msm_usb_chg_info)
+
+/* Vote against USB hardware low power mode */
+#define MSM_USB_EXT_CHG_BLOCK_LPM _IOW('M', 1, int)
+
+#endif /* __LINUX_USB_MSM_EXT_CHG_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 2f18351..1c9884c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -204,6 +204,10 @@
  * @pmic_id_irq: IRQ number assigned for PMIC USB ID line.
  * @mpm_otgsessvld_int: MPM wakeup pin assigned for OTG SESSVLD
  *              interrupt. Used when .otg_control == OTG_PHY_CONTROL.
+ * @mpm_dpshv_int: MPM wakeup pin assigned for DP SHV interrupt.
+ *		Used during host bus suspend.
+ * @mpm_dmshv_int: MPM wakeup pin assigned for DM SHV interrupt.
+ *		Used during host bus suspend.
  * @mhl_enable: indicates MHL connector or not.
  * @disable_reset_on_disconnect: perform USB PHY and LINK reset
  *              on USB cable disconnection.
@@ -235,6 +239,8 @@
 	void (*setup_gpio)(enum usb_otg_state state);
 	int pmic_id_irq;
 	unsigned int mpm_otgsessvld_int;
+	unsigned int mpm_dpshv_int;
+	unsigned int mpm_dmshv_int;
 	bool mhl_enable;
 	bool disable_reset_on_disconnect;
 	bool pnoc_errata_fix;
@@ -326,6 +332,7 @@
  * @xo_handle: TCXO buffer handle
  * @bus_perf_client: Bus performance client handle to request BUS bandwidth
  * @mhl_enabled: MHL driver registration successful and MHL enabled.
+ * @host_bus_suspend: indicates host bus suspend or not.
  * @chg_check_timer: The timer used to implement the workaround to detect
  *               very slow plug in of wall charger.
  */
@@ -381,6 +388,7 @@
 	struct msm_xo_voter *xo_handle;
 	uint32_t bus_perf_client;
 	bool mhl_enabled;
+	bool host_bus_suspend;
 	struct timer_list chg_check_timer;
 	/*
 	 * Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
@@ -405,6 +413,11 @@
 	 * analog regulators into LPM while going to USB low power mode.
 	 */
 #define ALLOW_PHY_REGULATORS_LPM	BIT(3)
+	/*
+	 * Allow PHY RETENTION mode before turning off the digital
+	 * voltage regulator(VDDCX) during host mode.
+	 */
+#define ALLOW_HOST_PHY_RETENTION	BIT(4)
 	unsigned long lpm_flags;
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index f3f4c3b..ba75cb9 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -82,6 +82,7 @@
 #define PHY_RETEN               (1 << 1) /* PHY retention enable/disable */
 #define PHY_IDHV_INTEN          (1 << 8) /* PHY ID HV interrupt */
 #define PHY_OTGSESSVLDHV_INTEN  (1 << 9) /* PHY Session Valid HV int. */
+#define PHY_CLAMP_DPDMSE_EN	(1 << 21) /* PHY mpm DP DM clamp enable */
 
 #define STS_PCI                 (1 << 2) /* R/WC - Port Change Detect */
 #define STS_URI                 (1 << 6) /* R/WC - RESET recv'd */
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index d6151c0..887b291 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -615,6 +615,7 @@
 #define PI_CODE_OFFSET 4
 #define AF_SIZE_OFFSET 6
 #define AF_LIST_OFFSET 7
+#define RT_A_B_FLAG_OFFSET 4
 /*FM states*/
 
 enum radio_state_t {
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2356791..d85cf09 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -648,6 +648,9 @@
 	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
 	int err;
 
+	if (addr_len < sizeof(struct sockaddr_nl))
+		return -EINVAL;
+
 	if (nladdr->nl_family != AF_NETLINK)
 		return -EINVAL;
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 68fd9d7..1dee449 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3031,10 +3031,10 @@
 	params.listen_interval =
 		nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
 
-	if (info->attrs[NL80211_ATTR_STA_AID])
-		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
-	else
+	if (info->attrs[NL80211_ATTR_PEER_AID])
 		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
+	else
+		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
 	if (!params.aid || params.aid > IEEE80211_MAX_AID)
 		return -EINVAL;
 
@@ -3104,7 +3104,8 @@
 			params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
 		}
 		/* TDLS peers cannot be added */
-		if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+		if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
+		    info->attrs[NL80211_ATTR_PEER_AID])
 			return -EINVAL;
 		/* but don't bother the driver with it */
 		params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
@@ -3116,7 +3117,8 @@
 		break;
 	case NL80211_IFTYPE_MESH_POINT:
 		/* TDLS peers cannot be added */
-		if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+		if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
+		    info->attrs[NL80211_ATTR_PEER_AID])
 			return -EINVAL;
 		break;
 	case NL80211_IFTYPE_STATION:
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 53cfb3e..de0b4da 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -35,9 +35,11 @@
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
 #include <mach/qdsp6v2/apr.h>
+#include <mach/subsystem_notif.h>
 #include "msm8x10-wcd.h"
 #include "wcd9xxx-resmgr.h"
 #include "msm8x10_wcd_registers.h"
+#include "../msm/qdsp6v2/q6core.h"
 
 #define MSM8X10_WCD_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
@@ -186,6 +188,11 @@
 
 struct msm8x10_wcd_i2c msm8x10_wcd_modules[MAX_MSM8X10_WCD_DEVICE];
 
+static void *adsp_state_notifier;
+
+static struct snd_soc_codec *registered_codec;
+#define ADSP_STATE_READY_TIMEOUT_MS 2000
+
 
 static int get_i2c_msm8x10_wcd_device_info(u16 reg,
 					   struct msm8x10_wcd_i2c **msm8x10_wcd)
@@ -2549,6 +2556,53 @@
 	return NULL;
 }
 
+static int msm8x10_wcd_device_up(struct snd_soc_codec *codec)
+{
+	pr_debug("%s: device up!\n", __func__);
+
+	mutex_lock(&codec->mutex);
+
+	msm8x10_wcd_bringup(codec);
+	msm8x10_wcd_codec_init_reg(codec);
+	msm8x10_wcd_update_reg_defaults(codec);
+
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+static int adsp_state_callback(struct notifier_block *nb, unsigned long value,
+			       void *priv)
+{
+	bool timedout;
+	unsigned long timeout;
+
+	if (value == SUBSYS_AFTER_POWERUP) {
+		pr_debug("%s: ADSP is about to power up. bring up codec\n",
+			 __func__);
+
+		timeout = jiffies +
+			  msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+		while (!(timedout = time_after(jiffies, timeout))) {
+			if (!q6core_is_adsp_ready()) {
+				pr_debug("%s: ADSP isn't ready\n", __func__);
+			} else {
+				pr_debug("%s: ADSP is ready\n", __func__);
+				msm8x10_wcd_device_up(registered_codec);
+				break;
+			}
+		}
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+	.notifier_call = adsp_state_callback,
+	.priority = -INT_MAX,
+};
+
+
 static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
 {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
@@ -2591,6 +2645,16 @@
 	msm8x10_wcd->mbhc_polling_active = false;
 	mutex_init(&msm8x10_wcd->codec_resource_lock);
 
+	registered_codec = codec;
+	adsp_state_notifier =
+	    subsys_notif_register_notifier("adsp",
+					   &adsp_state_notifier_block);
+	if (!adsp_state_notifier) {
+		pr_err("%s: Failed to register adsp state notifier\n",
+		       __func__);
+		registered_codec = NULL;
+		return -ENOMEM;
+	}
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wcd9320-tables.c b/sound/soc/codecs/wcd9320-tables.c
index e834b80..af9725c 100644
--- a/sound/soc/codecs/wcd9320-tables.c
+++ b/sound/soc/codecs/wcd9320-tables.c
@@ -680,7 +680,10 @@
 	[TAIKO_A_CDC_SPKR_CLIPDET_VAL5] = 1,
 	[TAIKO_A_CDC_SPKR_CLIPDET_VAL6] = 1,
 	[TAIKO_A_CDC_SPKR_CLIPDET_VAL7] = 1,
-
+	[TAIKO_A_CDC_PA_RAMP_B1_CTL] = 1,
+	[TAIKO_A_CDC_PA_RAMP_B2_CTL] = 1,
+	[TAIKO_A_CDC_PA_RAMP_B3_CTL] = 1,
+	[TAIKO_A_CDC_PA_RAMP_B4_CTL] = 1,
 };
 
 const u8 taiko_reset_reg_defaults[TAIKO_CACHE_SIZE] = {
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 4edcec6..03de4e0 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -1456,6 +1456,32 @@
 			analog_gain),
 };
 
+static int taiko_hph_impedance_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	uint32_t zl, zr;
+	bool hphr;
+	struct soc_multi_mixer_control *mc;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+
+	hphr = mc->shift;
+	wcd9xxx_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
+	pr_debug("%s: zl %u, zr %u\n", __func__, zl, zr);
+	ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+	SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+		       taiko_hph_impedance_get, NULL),
+	SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+		       taiko_hph_impedance_get, NULL),
+};
+
 static const char * const rx_mix1_text[] = {
 	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
 		"RX5", "RX6", "RX7"
@@ -6491,6 +6517,9 @@
 			ARRAY_SIZE(taiko_2_x_analog_gain_controls));
 	}
 
+	snd_soc_add_codec_controls(codec, impedance_detect_controls,
+				   ARRAY_SIZE(impedance_detect_controls));
+
 	control->num_rx_port = TAIKO_RX_MAX;
 	control->rx_chs = ptr;
 	memcpy(control->rx_chs, taiko_rx_chs, sizeof(taiko_rx_chs));
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index cd11703..e34dec1 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -18,6 +18,7 @@
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
 #include <linux/debugfs.h>
+#include <linux/list.h>
 #include <linux/mfd/wcd9xxx/core.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 #include <linux/mfd/wcd9xxx/wcd9320_registers.h>
@@ -36,6 +37,7 @@
 #include "wcd9306.h"
 #include "wcd9xxx-mbhc.h"
 #include "wcd9xxx-resmgr.h"
+#include "wcd9xxx-common.h"
 
 #define WCD9XXX_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
 			   SND_JACK_OC_HPHR | SND_JACK_LINEOUT | \
@@ -92,7 +94,10 @@
 #define WCD9XXX_GM_SWAP_THRES_MAX_MV 650
 #define WCD9XXX_THRESHOLD_MIC_THRESHOLD 200
 
-#define WCD9XXX_USLEEP_RANGE_MARGIN_US 1000
+#define WCD9XXX_USLEEP_RANGE_MARGIN_US 100
+
+/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
+#define WCD9XXX_WG_TIME_FACTOR_US	240
 
 #define WCD9XXX_IRQ_MBHC_JACK_SWITCH_DEFAULT 28
 
@@ -112,6 +117,12 @@
 	enum wcd9xxx_mbhc_plug_type _type;
 };
 
+struct wcd9xxx_register_save_node {
+	struct list_head lh;
+	u16 reg;
+	u16 value;
+};
+
 enum meas_type {
 	STA = 0,
 	DCE,
@@ -142,6 +153,9 @@
 	WCD9XXX_CURRENT_V_BR_H,
 };
 
+static int wcd9xxx_detect_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
+				    uint32_t *zr);
+
 static bool wcd9xxx_mbhc_polling(struct wcd9xxx_mbhc *mbhc)
 {
 	return mbhc->polling_active;
@@ -728,6 +742,7 @@
 			mbhc->micbias_enable_cb(mbhc->codec, false);
 			mbhc->micbias_enable = false;
 		}
+		mbhc->zl = mbhc->zr = 0;
 		pr_debug("%s: Reporting removal %d(%x)\n", __func__,
 			 jack_type, mbhc->hph_status);
 		wcd9xxx_jack_report(mbhc, &mbhc->headset_jack, mbhc->hph_status,
@@ -752,6 +767,7 @@
 				}
 				pr_debug("%s: Reporting removal (%x)\n",
 						__func__, mbhc->hph_status);
+				mbhc->zl = mbhc->zr = 0;
 				wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
 						    0, WCD9XXX_JACK_MASK);
 				mbhc->hph_status = 0;
@@ -775,6 +791,8 @@
 			pr_debug("%s: Enabling micbias\n", __func__);
 			mbhc->micbias_enable_cb(mbhc->codec, true);
 		}
+
+		wcd9xxx_detect_impedance(mbhc, &mbhc->zl, &mbhc->zr);
 		pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
 			 jack_type, mbhc->hph_status);
 		wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
@@ -2820,7 +2838,8 @@
 	dce_wait = (1000 * 512 * ncic * (nmeas + 1)) / (rate / 1000);
 	sta_wait = (1000 * 128 * (navg + 1)) / (rate / 1000);
 	mbhc->mbhc_data.t_dce = dce_wait;
-	mbhc->mbhc_data.t_sta = sta_wait;
+	/* give extra margin to sta for safety */
+	mbhc->mbhc_data.t_sta = sta_wait + 250;
 	mbhc->mbhc_data.t_sta_dce = ((1000 * 256) / (rate / 1000) *
 				     n_ready[idx]) + 10;
 
@@ -3575,6 +3594,300 @@
 	return ret;
 }
 
+static int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
+					struct list_head *list,
+					uint16_t reg, uint8_t mask,
+					uint8_t value)
+{
+	int rc;
+	struct wcd9xxx_register_save_node *node;
+
+	node = kmalloc(sizeof(*node), GFP_KERNEL);
+	if (unlikely(!node)) {
+		pr_err("%s: Not enough memory\n", __func__);
+		return -ENOMEM;
+	}
+	node->reg = reg;
+	node->value = snd_soc_read(codec, reg);
+	list_add(&node->lh, list);
+	if (mask == 0xFF)
+		rc = snd_soc_write(codec, reg, value);
+	else
+		rc = snd_soc_update_bits(codec, reg, mask, value);
+	return rc;
+}
+
+static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
+				     struct list_head *lh)
+{
+	int i;
+	struct snd_soc_codec *codec = mbhc->codec;
+
+	const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
+		{WCD9XXX_A_RX_HPH_OCP_CTL, 0x18, 0x00},
+		{WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
+		{WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
+		{WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x1A},
+		{WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDB},
+		{WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
+		{WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
+		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
+		{WCD9XXX_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
+		{WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
+		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
+		{WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
+		{WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
+		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0xff, 0x60},
+		{WCD9XXX_A_RX_COM_BIAS, 0xff, 0x80},
+		{WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
+		{WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
+		{WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
+		{WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
+		{WCD9XXX_A_NCP_EN, 0xff, 0xFF},
+		{WCD9XXX_A_BUCK_MODE_5, 0xff, 0x7B},
+		{WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
+		{WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
+		{WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++)
+		wcd9xxx_soc_update_bits_push(codec, lh,
+					     reg_set_paon[i].reg,
+					     reg_set_paon[i].mask,
+					     reg_set_paon[i].val);
+	pr_debug("%s: PAs are prepared\n", __func__);
+
+	return 0;
+}
+
+static void wcd9xxx_restore_registers(struct wcd9xxx_mbhc *mbhc,
+				      struct list_head *lh)
+{
+	struct wcd9xxx_register_save_node *node, *nodetmp;
+	struct snd_soc_codec *codec = mbhc->codec;
+
+	list_for_each_entry_safe(node, nodetmp, lh, lh) {
+		snd_soc_write(codec, node->reg, node->value);
+		list_del(&node->lh);
+		kfree(node);
+	}
+}
+
+static void wcd9xxx_unprepare_static_pa(struct wcd9xxx_mbhc *mbhc,
+					struct list_head *lh)
+{
+	wcd9xxx_restore_registers(mbhc, lh);
+}
+
+static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
+{
+	struct snd_soc_codec *codec = mbhc->codec;
+	const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
+			    WCD9XXX_WG_TIME_FACTOR_US;
+
+	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
+			    enable ? 0x30 : 0x0);
+	/* Wait for wave gen time to avoid pop noise */
+	usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
+		 enable ? "enabled" : "disabled", wg_time);
+	return 0;
+}
+
+static int wcd9xxx_detect_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
+				    uint32_t *zr)
+{
+	int i;
+	int ret = 0;
+	s16 l[3], r[3];
+	s16 *z[] = {
+		&l[0], &r[0], &r[1], &l[1], &l[2], &r[2],
+	};
+	LIST_HEAD(lh);
+	LIST_HEAD(lhpa);
+	struct snd_soc_codec *codec = mbhc->codec;
+	const int ramp_wait_us = 18 * 1000;
+	const int mux_wait_us = 25;
+	const int alphal = 364; /* 0.005555 * 65536 = 364.05 */
+	const int alphar = 364; /* 0.005555 * 65536 = 364.05 */
+	const int beta = 3855; /* 0.011765 * 5 * 65536 = 3855.15 */
+	const int rref = 11333; /* not scaled up */
+	const int shift = 16;
+	int64_t rl, rr = 0; /* milliohm */
+	const struct wcd9xxx_reg_mask_val reg_set_mux[] = {
+		/* Phase 1 */
+		/* Set MBHC_MUX for HPHL without ical */
+		{WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0},
+		/* Set MBHC_MUX for HPHR without ical */
+		{WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xA0},
+		/* Set MBHC_MUX for HPHR with ical */
+		{WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF8},
+		/* Set MBHC_MUX for HPHL with ical */
+		{WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0},
+
+		/* Phase 2 */
+		{WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0},
+		/* Set MBHC_MUX for HPHR without ical and wait for 25us */
+		{WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xA0},
+	};
+
+	pr_debug("%s: enter\n", __func__);
+	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
+
+	/*
+	 * Impedance detection is an intrusive function as it mutes RX paths,
+	 * enable PAs and etc.  Therefore codec drvier including ALSA
+	 * shouldn't read and write hardware registers during detection.
+	 */
+	mutex_lock(&codec->mutex);
+
+	WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
+	wcd9xxx_resmgr_get_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
+	wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
+	WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+
+	pr_debug("%s: Setting impedance detection\n", __func__);
+	wcd9xxx_prepare_static_pa(mbhc, &lhpa);
+	wcd9xxx_enable_static_pa(mbhc, true);
+
+	/*
+	 * save old value of registers and write the new value to restore old
+	 * value back, WCD9XXX_A_CDC_PA_RAMP_B{1,2,3,4}_CTL registers don't
+	 * need to be restored as those are solely used by impedance detection.
+	 */
+#define __w(reg, mask, value)						  \
+	do {								  \
+		ret = wcd9xxx_soc_update_bits_push(codec, &lh, reg, mask, \
+						   value);		  \
+		if (ret < 0)						  \
+			return ret;					  \
+	} while (0)
+
+	/* Reset the PA Ramp */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
+	/*
+	 * Connect the PA Ramp to PA chain and release reset with keep it
+	 * connected.
+	 */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
+	/* Program the PA Ramp to FS_48K, L shift 1 and sample num to 24 */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL, 0x3 << 4 | 0x6);
+	/* 0x56 for 10mv.  0xC0 is for 50mv */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0xC0);
+	/* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
+	__w(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0);
+	__w(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
+	__w(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
+	__w(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0x8C);
+	/* Change NSA and NAVG */
+	__w(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x4 << 4, 0x4 << 4);
+	__w(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x10);
+	/* Reset MBHC and set it up for STA */
+	__w(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
+	__w(WCD9XXX_A_CDC_MBHC_EN_CTL, 0xFF, 0x02);
+	__w(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
+
+	/* Set HPH_MBHC for zdet */
+	__w(WCD9XXX_A_MBHC_HPH, 0xB3, 0x80);
+
+	pr_debug("%s: Performing impedance detection\n", __func__);
+	/* Phase 1 */
+	for (i = 0; i < ARRAY_SIZE(reg_set_mux) - 2; i++) {
+		__w(reg_set_mux[i].reg, reg_set_mux[i].mask,
+		    reg_set_mux[i].val);
+		/* 25us is required after mux change to settle down */
+		usleep_range(mux_wait_us,
+			     mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+		*(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, false, false);
+	}
+
+	/* Phase 2 */
+	/* Start the PA ramp on HPH L and R */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
+	/* Ramp generator takes ~17ms */
+	usleep_range(ramp_wait_us,
+		     ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+
+	/* Disable Ical */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
+	/* Ramp generator takes ~17ms */
+	usleep_range(ramp_wait_us,
+		     ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	for (; i < ARRAY_SIZE(reg_set_mux); i++) {
+		__w(reg_set_mux[i].reg, reg_set_mux[i].mask,
+		    reg_set_mux[i].val);
+		/* 25us is required after mux change to settle down */
+		usleep_range(mux_wait_us,
+			     mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+		*(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, false, false);
+	}
+
+	/* Ramp HPH L & R back to Zero */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
+	/* Ramp generator takes ~17ms */
+	usleep_range(ramp_wait_us,
+		     ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
+#undef __w
+
+	/* Clean up starts */
+	/* Turn off PA ramp generator */
+	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
+	wcd9xxx_enable_static_pa(mbhc, false);
+	wcd9xxx_restore_registers(mbhc, &lh);
+	wcd9xxx_unprepare_static_pa(mbhc, &lhpa);
+
+	mutex_unlock(&codec->mutex);
+
+	WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
+	wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
+	wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
+	WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+
+	rl = (int)(l[0] - l[1]) * 1000 / (l[0] - l[2]);
+	rl = rl * rref * alphal;
+	rl = rl >> shift;
+	rl = rl * beta;
+	rl = rl >> shift;
+	*zl = rl;
+
+	rr = (int)(r[0] - r[1]) * 1000 / (r[0] - r[2]);
+	rr = rr * rref  * alphar;
+	rr = rr >> shift;
+	rr = rr * beta;
+	rr = rr >> shift;
+	*zr = rr;
+
+	pr_debug("%s: L0: 0x%x(%d), L1: 0x%x(%d), L2: 0x%x(%d), rl: %lld\n",
+		 __func__,
+		 l[0] & 0xffff, l[0], l[1] & 0xffff, l[1], l[2] & 0xffff, l[2],
+		 rl);
+	pr_debug("%s: R0: 0x%x(%d), R1: 0x%x(%d), R2: 0x%x(%d), rr: %lld\n",
+		 __func__,
+		 r[0] & 0xffff, r[0], r[1] & 0xffff, r[1], r[2] & 0xffff, r[2],
+		 rr);
+	pr_debug("%s: RL %d milliohm, RR %d milliohm\n", __func__, *zl, *zr);
+	pr_debug("%s: Impedance detection completed\n", __func__);
+
+	return ret;
+}
+
+int wcd9xxx_mbhc_get_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
+			       uint32_t *zr)
+{
+	WCD9XXX_BCL_LOCK(mbhc->resmgr);
+	*zl = mbhc->zl;
+	*zr = mbhc->zr;
+	WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
+
+	if (*zl && *zr)
+		return 0;
+	else
+		return -EINVAL;
+}
+
 /*
  * wcd9xxx_mbhc_init : initialize MBHC internal structures.
  *
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 02ecced..1f6502f 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -291,6 +291,9 @@
 	bool micbias_enable;
 	int (*micbias_enable_cb) (struct snd_soc_codec*,  bool);
 
+	/* impedance of hphl and hphr */
+	uint32_t zl, zr;
+
 	u32 rco_clk_rate;
 
 #ifdef CONFIG_DEBUG_FS
@@ -365,4 +368,6 @@
 void *wcd9xxx_mbhc_cal_btn_det_mp(
 			    const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
 			    const enum wcd9xxx_mbhc_btn_det_mem mem);
+int wcd9xxx_mbhc_get_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
+			       uint32_t *zr);
 #endif /* __WCD9XXX_MBHC_H__ */
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index f67af9b..0b7e7f2 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -208,6 +208,7 @@
 static int msm_hdmi_rx_ch = 2;
 static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
 static int msm_proxy_rx_ch = 2;
+static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
 
 static struct mutex cdc_mclk_mutex;
 static struct clk *codec_clk;
@@ -720,6 +721,8 @@
 static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
 	"Five",	"Six", "Seven", "Eight"};
 
+static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+					"KHZ_192"};
 static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
@@ -940,6 +943,57 @@
 	return 1;
 }
 
+static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (hdmi_rx_sample_rate) {
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 2;
+		break;
+
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 1;
+		break;
+
+	case SAMPLING_RATE_48KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+				hdmi_rx_sample_rate);
+
+	return 0;
+}
+
+static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: ucontrol value = %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 2:
+		hdmi_rx_sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 1:
+		hdmi_rx_sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
+	}
+
+	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+			hdmi_rx_sample_rate);
+
+	return 0;
+}
+
 static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -1055,7 +1109,7 @@
 				hdmi_rx_bit_format);
 	if (channels->max < 2)
 		channels->min = channels->max = 2;
-	rate->min = rate->max = 48000;
+	rate->min = rate->max = hdmi_rx_sample_rate;
 	channels->min = channels->max = msm_hdmi_rx_ch;
 
 	return 0;
@@ -1324,6 +1378,7 @@
 	SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
 	SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
 	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(3, hdmi_rx_sample_rate_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1347,6 +1402,8 @@
 			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
 		     msm_btsco_rate_get, msm_btsco_rate_put),
+	SOC_ENUM_EXT("HDMI_RX SampleRate", msm_snd_enum[7],
+			hdmi_rx_sample_rate_get, hdmi_rx_sample_rate_put),
 };
 
 static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 60f4669..094c58b 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2356,10 +2356,11 @@
 	}
 	if (common.ec_ref_ext == true) {
 		ret = voice_send_set_device_cmd_v2(v);
-		if (ret < 0)
+		if (ret < 0) {
 			pr_err("%s:  set device V2 failed rc =%x\n",
 			       __func__, ret);
 			goto fail;
+		}
 	}
 	/* send cvs cal */
 	ret = voice_send_cvs_map_memory_cmd(v);
@@ -3354,10 +3355,11 @@
 	if (v->voc_state == VOC_CHANGE) {
 		if (common.ec_ref_ext == true) {
 			ret = voice_send_set_device_cmd_v2(v);
-			if (ret < 0)
+			if (ret < 0) {
 				pr_err("%s: set device V2 failed\n"
 				       "rc =%x\n", __func__, ret);
 				goto fail;
+			}
 		} else {
 			ret = voice_send_set_device_cmd(v);
 			if (ret < 0) {
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 687f10d..9f4e189 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -36,6 +36,7 @@
 #include "msm-compr-q6-v2.h"
 #include "msm-pcm-routing-v2.h"
 #include "audio_ocmem.h"
+#include <sound/tlv.h>
 
 #define COMPRE_CAPTURE_NUM_PERIODS	16
 /* Allocate the worst case frame size for compressed audio */
@@ -48,13 +49,14 @@
 					  COMPRE_CAPTURE_HEADER_SIZE) * \
 					  MAX_NUM_FRAMES_PER_BUFFER)
 #define COMPRE_OUTPUT_METADATA_SIZE	(sizeof(struct output_meta_data_st))
+#define COMPRESSED_LR_VOL_MAX_STEPS	0x20002000
 
+const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0,
+			    COMPRESSED_LR_VOL_MAX_STEPS);
 struct snd_msm {
-	struct msm_audio *prtd;
-	unsigned volume;
 	atomic_t audio_ocmem_req;
 };
-static struct snd_msm compressed_audio = {NULL, 0x20002000} ;
+static struct snd_msm compressed_audio;
 
 static struct audio_locks the_locks;
 
@@ -609,7 +611,6 @@
 	populate_codec_list(compr, runtime);
 	runtime->private_data = compr;
 	atomic_set(&prtd->eos, 0);
-	compressed_audio.prtd =  &compr->prtd;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (!atomic_cmpxchg(&compressed_audio.audio_ocmem_req, 0, 1))
 			audio_ocmem_process_req(AUDIO, true);
@@ -621,33 +622,29 @@
 	return 0;
 }
 
-int compressed_set_volume(unsigned volume)
+static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume)
 {
 	int rc = 0;
 	int avg_vol = 0;
 	int lgain = (volume >> 16) & 0xFFFF;
 	int rgain = volume & 0xFFFF;
-	if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
+	if (prtd && prtd->audio_client) {
 		pr_debug("%s: channels %d volume 0x%x\n", __func__,
-			compressed_audio.prtd->channel_mode, volume);
-		if ((compressed_audio.prtd->channel_mode <= 2) &&
+			prtd->channel_mode, volume);
+		if ((prtd->channel_mode == 2) &&
 			(lgain != rgain)) {
 			pr_debug("%s: call q6asm_set_lrgain\n", __func__);
-			rc = q6asm_set_lrgain(
-				compressed_audio.prtd->audio_client,
-				lgain, rgain);
+			rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain);
 		} else {
 			avg_vol = (lgain + rgain)/2;
 			pr_debug("%s: call q6asm_set_volume\n", __func__);
-			rc = q6asm_set_volume(
-				compressed_audio.prtd->audio_client, avg_vol);
+			rc = q6asm_set_volume(prtd->audio_client, avg_vol);
 		}
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
 				__func__, rc);
 		}
 	}
-	compressed_audio.volume = volume;
 	return rc;
 }
 
@@ -673,7 +670,6 @@
 		atomic_read(&compressed_audio.audio_ocmem_req));
 	prtd->pcm_irq_pos = 0;
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
-	compressed_audio.prtd = NULL;
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
 		msm_pcm_routing_dereg_phy_stream(
@@ -815,17 +811,15 @@
 		    (params_periods(params) <= runtime->hw.channels_max))
 			prtd->channel_mode = params_channels(params);
 
-		ret = compressed_set_volume(0);
+		ret = compressed_set_volume(prtd, 0);
 		if (ret < 0)
 			pr_err("%s : Set Volume failed : %d", __func__, ret);
 
-		ret = q6asm_set_softpause(compressed_audio.prtd->audio_client,
-								&softpause);
+		ret = q6asm_set_softpause(prtd->audio_client, &softpause);
 		if (ret < 0)
 			pr_err("%s: Send SoftPause Param failed ret=%d\n",
 				__func__, ret);
-		ret = q6asm_set_softvolume(compressed_audio.prtd->audio_client,
-								&softvol);
+		ret = q6asm_set_softvolume(prtd->audio_client, &softvol);
 		if (ret < 0)
 			pr_err("%s: Send SoftVolume Param failed ret=%d\n",
 				__func__, ret);
@@ -1165,6 +1159,66 @@
 	return 0;
 }
 
+static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+	int volume = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: volume : %x\n", __func__, volume);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		rc = compressed_set_volume(prtd, volume);
+
+	return rc;
+}
+
+static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+
+	pr_debug("%s\n", __func__);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		ucontrol->value.integer.value[0] = prtd->volume;
+	return 0;
+}
+
+static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = 0;
+	struct snd_pcm *pcm = rtd->pcm;
+	struct snd_pcm_volume *volume_info;
+	struct snd_kcontrol *kctl;
+
+	dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__);
+	ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				      NULL, 1, rtd->dai_link->be_id,
+				      &volume_info);
+	if (ret < 0)
+		return ret;
+	kctl = volume_info->kctl;
+	kctl->put = msm_compr_volume_ctl_put;
+	kctl->get = msm_compr_volume_ctl_get;
+	kctl->tlv.p = compr_rx_vol_gain;
+	return 0;
+}
 
 static struct snd_pcm_ops msm_compr_ops = {
 	.open	   = msm_compr_open,
@@ -1185,6 +1239,10 @@
 
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	ret = msm_compr_add_controls(rtd);
+	if (ret)
+		pr_err("%s, kctl add failed\n", __func__);
 	return ret;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 16df886..0cf044c 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -264,11 +264,12 @@
 
 static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
 	.playback = {
-		.rates = SNDRV_PCM_RATE_48000,
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+		 SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.channels_min = 2,
 		.channels_max = 8,
-		.rate_max =     48000,
+		.rate_max =     192000,
 		.rate_min =	48000,
 	},
 	.ops = &msm_dai_q6_hdmi_ops,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index d31e2c5..1434970 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -42,6 +42,10 @@
 };
 enum {
 	STATUS_PORT_STARTED, /* track if AFE port has started */
+	/* track AFE Tx port status for bi-directional transfers */
+	STATUS_TX_PORT,
+	/* track AFE Rx port status for bi-directional transfers */
+	STATUS_RX_PORT,
 	STATUS_MAX
 };
 
@@ -70,8 +74,9 @@
 };
 
 struct msm_dai_q6_auxpcm_dai_data {
+	/* BITMAP to track Rx and Tx port usage count */
+	DECLARE_BITMAP(auxpcm_port_status, STATUS_MAX);
 	struct mutex rlock; /* auxpcm dev resource lock */
-	int rcnt; /* auxpcm dev resource usage count */
 	u16 rx_pid; /* AUXPCM RX AFE port ID */
 	u16 tx_pid; /* AUXPCM TX AFE port ID */
 	struct afe_clk_cfg clk_cfg; /* hold LPASS clock configuration */
@@ -116,7 +121,8 @@
 
 	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_dai_data->rcnt) {
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
 		/* AUXPCM DAI in use */
 		if (dai_data->rate != params_rate(params)) {
 			dev_err(dai->dev, "%s: rate mismatch of running DAI\n",
@@ -184,36 +190,46 @@
 {
 	int rc = 0;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data =
 		dev_get_drvdata(dai->dev);
 
 	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_dai_data->rcnt == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just return\n",
+	if (!(test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	      test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))) {
+		dev_dbg(dai->dev, "%s(): dai->id %d PCM ports already closed\n",
 				__func__, dai->id);
-		mutex_unlock(&aux_dai_data->rlock);
-		return;
+		goto exit;
 	}
 
-	aux_dai_data->rcnt--;
-
-	if (aux_dai_data->rcnt > 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
-			__func__, dai->id, aux_dai_data->rcnt);
-		mutex_unlock(&aux_dai_data->rlock);
-		return;
-	} else if (aux_dai_data->rcnt < 0) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d < 0\n",
-			__func__, dai->id, aux_dai_data->rcnt);
-		aux_dai_data->rcnt = 0;
-		mutex_unlock(&aux_dai_data->rlock);
-		return;
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status))
+			clear_bit(STATUS_TX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+		else {
+			dev_dbg(dai->dev, "%s(): PCM_TX port already closed\n",
+				__func__);
+			goto exit;
+		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))
+			clear_bit(STATUS_RX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+		else {
+			dev_dbg(dai->dev, "%s(): PCM_RX port already closed\n",
+				__func__);
+			goto exit;
+		}
+	}
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		dev_dbg(dai->dev, "%s(): cannot shutdown PCM ports\n",
+			__func__);
+		goto exit;
 	}
 
-	dev_dbg(dai->dev, "%s: dai->id = %d aux_pcm_count = %d\n", __func__,
-		dai->id, aux_dai_data->rcnt);
+	dev_dbg(dai->dev, "%s: dai->id = %d closing PCM AFE ports\n",
+			__func__, dai->id);
 
 	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
 
@@ -229,12 +245,9 @@
 	afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			 sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = 0;
-	afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-
+exit:
 	mutex_unlock(&aux_dai_data->rlock);
+	return;
 }
 
 static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
@@ -246,7 +259,6 @@
 	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
 	int rc = 0;
 	unsigned long pcm_clk_rate;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
 
 	auxpcm_pdata = dai->dev->platform_data;
@@ -254,32 +266,39 @@
 
 	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_dai_data->rcnt == 2) { /* xrun case ? */
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just return.\n",
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (test_bit(STATUS_TX_PORT,
+				aux_dai_data->auxpcm_port_status)) {
+			dev_dbg(dai->dev, "%s(): PCM_TX port already ON\n",
+				__func__);
+			goto exit;
+		} else
+			set_bit(STATUS_TX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+	} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (test_bit(STATUS_RX_PORT,
+				aux_dai_data->auxpcm_port_status)) {
+			dev_dbg(dai->dev, "%s(): PCM_RX port already ON\n",
+				__func__);
+			goto exit;
+		} else
+			set_bit(STATUS_RX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+	}
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) &&
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		dev_dbg(dai->dev, "%s(): PCM ports already set\n", __func__);
+		goto exit;
+	}
+
+	dev_dbg(dai->dev, "%s: dai->id:%d  opening afe ports\n",
 			__func__, dai->id);
-		mutex_unlock(&aux_dai_data->rlock);
-		return 0;
-	} else if (aux_dai_data->rcnt > 2) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d > 2\n",
-			__func__, dai->id, aux_dai_data->rcnt);
-		mutex_unlock(&aux_dai_data->rlock);
-		return 0;
-	}
-
-	aux_dai_data->rcnt++;
-	if (aux_dai_data->rcnt == 2)  {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after increment\n",
-				__func__, dai->id, aux_dai_data->rcnt);
-		mutex_unlock(&aux_dai_data->rlock);
-		return 0;
-	}
-
-	dev_dbg(dai->dev, "%s:dai->id:%d  aux_pcm_count = %d. opening afe\n",
-		__func__, dai->id, aux_dai_data->rcnt);
 
 	rc = afe_q6_interface_prepare();
-	if (IS_ERR_VALUE(rc))
+	if (IS_ERR_VALUE(rc)) {
 		dev_err(dai->dev, "fail to open AFE APR\n");
+		goto fail;
+	}
 
 	/*
 	 * For AUX PCM Interface the below sequence of clk
@@ -300,18 +319,14 @@
 	} else {
 		dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
 			dai_data->rate);
-		mutex_unlock(&aux_dai_data->rlock);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto fail;
 	}
 
 	memcpy(lpass_pcm_src_clk, &lpass_clk_cfg_default,
 			sizeof(struct afe_clk_cfg));
 	lpass_pcm_src_clk->clk_val1 = pcm_clk_rate;
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-
 	rc = afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	if (rc < 0) {
 		dev_err(dai->dev,
@@ -328,18 +343,17 @@
 		goto fail;
 	}
 
-	rc = afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-	if (rc < 0) {
-		dev_err(dai->dev,
-			"%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
-			__func__);
-		goto fail;
-	}
-
 	afe_open(aux_dai_data->rx_pid, &dai_data->port_config, dai_data->rate);
 	afe_open(aux_dai_data->tx_pid, &dai_data->port_config, dai_data->rate);
+	goto exit;
 
 fail:
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+	else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+
+exit:
 	mutex_unlock(&aux_dai_data->rlock);
 	return rc;
 }
@@ -377,40 +391,30 @@
 {
 	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	int rc;
 
 	aux_dai_data = dev_get_drvdata(dai->dev);
 
-	if (aux_dai_data->rcnt == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean up and return\n",
-			__func__, dai->id);
-		goto done;
-	}
-
 	dev_dbg(dai->dev, "%s(): dai->id %d closing afe\n",
 		__func__, dai->id);
 
-	rc = afe_close(aux_dai_data->rx_pid); /* can block */
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
-
-	rc = afe_close(aux_dai_data->tx_pid);
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		rc = afe_close(aux_dai_data->rx_pid); /* can block */
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AUXPCM RX AFE port\n");
+		rc = afe_close(aux_dai_data->tx_pid);
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AUXPCM TX AFE port\n");
+		clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+		clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+	}
 
 	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
-
 	lpass_pcm_src_clk->clk_val1 = 0;
 	afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			 sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = 0;
-	afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-
-done:
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index 9ace410..ca2afaf 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -231,7 +231,7 @@
 
 static int map_device_to_dolby_endpoint(int device)
 {
-	int i, dolby_dap_device = DOLBY_ENDP_INT_SPEAKERS;
+	int i, dolby_dap_device = DOLBY_ENDP_EXT_SPEAKERS;
 	for (i = 0; i < NUM_DOLBY_ENDP_DEVICE; i++) {
 		if (dolby_dap_endp_params[i].device == device) {
 			dolby_dap_device = dolby_dap_endp_params[i].dap_device;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index eeb1745..caf77ee 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -41,12 +41,15 @@
 #include "msm-pcm-routing-v2.h"
 #include "audio_ocmem.h"
 #include <sound/pcm.h>
+#include <sound/tlv.h>
 
+#define LPA_LR_VOL_MAX_STEPS	0x20002000
+
+const DECLARE_TLV_DB_LINEAR(lpa_rx_vol_gain, 0,
+			    LPA_LR_VOL_MAX_STEPS);
 static struct audio_locks the_locks;
 
 struct snd_msm {
-	struct msm_audio *prtd;
-	unsigned volume;
 	atomic_t audio_ocmem_req;
 };
 static struct snd_msm lpa_audio;
@@ -414,7 +417,6 @@
 	atomic_set(&prtd->stop, 1);
 	atomic_set(&lpa_audio.audio_ocmem_req, 0);
 	runtime->private_data = prtd;
-	lpa_audio.prtd = prtd;
 	if (!atomic_cmpxchg(&lpa_audio.audio_ocmem_req, 0, 1))
 		audio_ocmem_process_req(AUDIO, true);
 	else
@@ -424,19 +426,19 @@
 	return 0;
 }
 
-int lpa_set_volume(unsigned volume)
+static int lpa_set_volume(struct msm_audio *prtd, uint32_t volume)
 {
 	int rc = 0;
-	if (lpa_audio.prtd && lpa_audio.prtd->audio_client) {
-		rc = q6asm_set_lrgain(lpa_audio.prtd->audio_client,
-						(volume >> 16) & 0xFFFF,
-						volume & 0xFFFF);
+	if (prtd && prtd->audio_client) {
+		rc = q6asm_set_lrgain(prtd->audio_client,
+				      (volume >> 16) & 0xFFFF, volume & 0xFFFF);
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
-					__func__, rc);
+						__func__, rc);
+		} else {
+			prtd->volume = volume;
 		}
 	}
-	lpa_audio.volume = volume;
 	return rc;
 }
 
@@ -476,10 +478,8 @@
 			atomic_dec(&lpa_audio.audio_ocmem_req);
 		else if (atomic_cmpxchg(&lpa_audio.audio_ocmem_req, 1, 0))
 			audio_ocmem_process_req(AUDIO, false);
-
 		pr_debug("%s: req: %d\n", __func__,
 			atomic_read(&lpa_audio.audio_ocmem_req));
-		lpa_audio.prtd = NULL;
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
@@ -594,12 +594,12 @@
 		prtd->audio_client->perf_mode,
 		prtd->session_id, substream->stream);
 
-	lpa_set_volume(0);
-	ret = q6asm_set_softpause(lpa_audio.prtd->audio_client, &softpause);
+	lpa_set_volume(prtd, 0);
+	ret = q6asm_set_softpause(prtd->audio_client, &softpause);
 	if (ret < 0)
 		pr_err("%s: Send SoftPause Param failed ret=%d\n",
 			__func__, ret);
-	ret = q6asm_set_softvolume(lpa_audio.prtd->audio_client, &softvol);
+	ret = q6asm_set_softvolume(prtd->audio_client, &softvol);
 	if (ret < 0)
 		pr_err("%s: Send SoftVolume Param failed ret=%d\n",
 			__func__, ret);
@@ -695,6 +695,67 @@
 	return snd_pcm_lib_ioctl(substream, cmd, arg);
 }
 
+static int msm_lpa_volume_ctl_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+	int volume = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: volume : %x\n", __func__, volume);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		rc = lpa_set_volume(prtd, volume);
+
+	return rc;
+}
+
+static int msm_lpa_volume_ctl_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+
+	pr_debug("%s\n", __func__);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		ucontrol->value.integer.value[0] = prtd->volume;
+	return 0;
+}
+
+static int msm_lpa_add_controls(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = 0;
+	struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+	struct snd_pcm_volume *volume_info;
+	struct snd_kcontrol *kctl;
+
+	dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__);
+	ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				      NULL, 1, rtd->dai_link->be_id,
+				      &volume_info);
+	if (ret < 0)
+		return ret;
+	kctl = volume_info->kctl;
+	kctl->put = msm_lpa_volume_ctl_put;
+	kctl->get = msm_lpa_volume_ctl_get;
+	kctl->tlv.p = lpa_rx_vol_gain;
+	return 0;
+}
+
 static struct snd_pcm_ops msm_pcm_ops = {
 	.open           = msm_pcm_open,
 	.hw_params	= msm_pcm_hw_params,
@@ -714,6 +775,10 @@
 
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	ret = msm_lpa_add_controls(rtd);
+	if (ret)
+		pr_err("%s, kctl add failed\n", __func__);
 	return ret;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index 6ded0d9..f7719ed 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -86,6 +86,7 @@
 	char channel_map[8];
 	int cmd_interrupt;
 	bool meta_data_mode;
+	uint32_t volume;
 };
 
 struct output_meta_data_st {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index c1bc17b..76a525d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -85,23 +85,14 @@
 
 #define INT_RX_VOL_MAX_STEPS 0x2000
 #define INT_RX_VOL_GAIN 0x2000
-#define INT_RX_LR_VOL_MAX_STEPS 0x20002000
 static int msm_route_fm_vol_control;
 static const DECLARE_TLV_DB_LINEAR(fm_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 
-static int msm_route_lpa_vol_control;
-static const DECLARE_TLV_DB_LINEAR(lpa_rx_vol_gain, 0,
-			INT_RX_LR_VOL_MAX_STEPS);
-
 static int msm_route_multimedia2_vol_control;
 static const DECLARE_TLV_DB_LINEAR(multimedia2_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 
-static int msm_route_compressed_vol_control;
-static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
-			INT_RX_LR_VOL_MAX_STEPS);
-
 static int msm_route_multimedia5_vol_control;
 static const DECLARE_TLV_DB_LINEAR(multimedia5_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
@@ -1031,23 +1022,6 @@
 	return 0;
 }
 
-static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
-	return 0;
-}
-
-static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	if (!lpa_set_volume(ucontrol->value.integer.value[0]))
-		msm_route_lpa_vol_control =
-			ucontrol->value.integer.value[0];
-
-	return 0;
-}
-
 static int msm_routing_get_multimedia2_vol_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1086,24 +1060,6 @@
 	return 0;
 }
 
-static int msm_routing_get_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-
-	ucontrol->value.integer.value[0] = msm_route_compressed_vol_control;
-	return 0;
-}
-
-static int msm_routing_set_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	if (!compressed_set_volume(ucontrol->value.integer.value[0]))
-		msm_route_compressed_vol_control =
-			ucontrol->value.integer.value[0];
-
-	return 0;
-}
-
 static int msm_routing_get_channel_map_mixer(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -2447,12 +2403,6 @@
 	msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
 };
 
-static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
-	SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
-	INT_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
-	msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
-};
-
 static const struct snd_kcontrol_new multimedia2_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("HIFI2 RX Volume", SND_SOC_NOPM, 0,
 	INT_RX_VOL_GAIN, 0, msm_routing_get_multimedia2_vol_mixer,
@@ -2465,12 +2415,6 @@
 	msm_routing_set_multimedia5_vol_mixer, multimedia5_rx_vol_gain),
 };
 
-static const struct snd_kcontrol_new compressed_vol_mixer_controls[] = {
-	SOC_SINGLE_EXT_TLV("COMPRESSED RX Volume", SND_SOC_NOPM, 0,
-	INT_RX_VOL_GAIN, 0, msm_routing_get_compressed_vol_mixer,
-	msm_routing_set_compressed_vol_mixer, compressed_rx_vol_gain),
-};
-
 static const struct snd_kcontrol_new multi_ch_channel_map_mixer_controls[] = {
 	SOC_SINGLE_MULTI_EXT("Playback Channel Map", SND_SOC_NOPM, 0, 16,
 	0, 8, msm_routing_get_channel_map_mixer,
@@ -3764,10 +3708,6 @@
 			ARRAY_SIZE(int_fm_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
-				lpa_vol_mixer_controls,
-			ARRAY_SIZE(lpa_vol_mixer_controls));
-
-	snd_soc_add_platform_controls(platform,
 				eq_enable_mixer_controls,
 			ARRAY_SIZE(eq_enable_mixer_controls));
 
@@ -3788,10 +3728,6 @@
 			ARRAY_SIZE(multimedia5_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
-				compressed_vol_mixer_controls,
-			ARRAY_SIZE(compressed_vol_mixer_controls));
-
-	snd_soc_add_platform_controls(platform,
 				lpa_SRS_trumedia_controls,
 			ARRAY_SIZE(lpa_SRS_trumedia_controls));
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 0d87735..4ce0db5 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -143,14 +143,10 @@
 
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
 
-int lpa_set_volume(unsigned volume);
-
 int msm_routing_check_backend_enabled(int fedai_id);
 
 int multi_ch_pcm_set_volume(unsigned volume);
 
-int compressed_set_volume(unsigned volume);
-
 uint32_t get_adm_rx_topology(void);
 
 uint32_t get_adm_tx_topology(void);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 5c420ed..071db4e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -617,12 +617,36 @@
 
 static __devinit int msm_pcm_probe(struct platform_device *pdev)
 {
+	int rc;
+
+	if (!is_voc_initialized()) {
+		pr_debug("%s: voice module not initialized yet, deferring probe()\n",
+		       __func__);
+
+		rc = -EPROBE_DEFER;
+		goto done;
+	}
+
+	rc = voc_alloc_cal_shared_memory();
+	if (rc == -EPROBE_DEFER) {
+		pr_debug("%s: memory allocation for calibration deferred %d\n",
+			 __func__, rc);
+
+		goto done;
+	} else if (rc < 0) {
+		pr_err("%s: memory allocation for calibration failed %d\n",
+		       __func__, rc);
+	}
+
 	if (pdev->dev.of_node)
 		dev_set_name(&pdev->dev, "%s", "msm-pcm-voice");
 
 	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
-	return snd_soc_register_platform(&pdev->dev,
-				   &msm_soc_platform);
+	rc = snd_soc_register_platform(&pdev->dev,
+				       &msm_soc_platform);
+
+done:
+	return rc;
 }
 
 static int msm_pcm_remove(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index f17fe5b..ae454a8 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -817,8 +817,15 @@
 		}
 		voc_register_mvs_cb(voip_process_ul_pkt,
 					voip_process_dl_pkt, prtd);
-		voc_start_voice_call(voc_get_session_id(VOIP_SESSION_NAME));
+		ret = voc_start_voice_call(
+				voc_get_session_id(VOIP_SESSION_NAME));
 
+		if (ret < 0) {
+			pr_err("%s: voc_start_voice_call() failed err %d",
+			       __func__, ret);
+
+			goto done;
+		}
 		prtd->state = VOIP_STARTED;
 	}
 done:
@@ -1132,12 +1139,42 @@
 
 static __devinit int msm_pcm_probe(struct platform_device *pdev)
 {
+	int rc;
+
+	if (!is_voc_initialized()) {
+		pr_debug("%s: voice module not initialized yet, deferring probe()\n",
+		       __func__);
+
+		rc = -EPROBE_DEFER;
+		goto done;
+	}
+
+	rc = voc_alloc_cal_shared_memory();
+	if (rc == -EPROBE_DEFER) {
+		pr_debug("%s: memory allocation for calibration deferred %d\n",
+			 __func__, rc);
+
+		goto done;
+	} else if (rc < 0) {
+		pr_err("%s: memory allocation for calibration failed %d\n",
+		       __func__, rc);
+	}
+
+	rc = voc_alloc_voip_shared_memory();
+	if (rc < 0) {
+		pr_err("%s: error allocating shared mem err %d\n",
+		       __func__, rc);
+	}
+
 	if (pdev->dev.of_node)
 		dev_set_name(&pdev->dev, "%s", "msm-voip-dsp");
 
 	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
-	return snd_soc_register_platform(&pdev->dev,
-				   &msm_soc_platform);
+	rc = snd_soc_register_platform(&pdev->dev,
+				       &msm_soc_platform);
+
+done:
+	return rc;
 }
 
 static int msm_pcm_remove(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 9fb4eae..f268171 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -48,6 +48,7 @@
 };
 
 static struct common_data common;
+static bool module_initialized;
 
 static int voice_send_enable_vocproc_cmd(struct voice_data *v);
 static int voice_send_netid_timing_cmd(struct voice_data *v);
@@ -84,6 +85,14 @@
 
 static int voice_send_set_pp_enable_cmd(struct voice_data *v,
 					uint32_t module_id, int enable);
+static int is_cal_memory_allocated(void);
+static int is_voip_memory_allocated(void);
+static int voice_alloc_cal_mem_map_table(void);
+static int voice_alloc_oob_shared_mem(void);
+static int voice_free_oob_shared_mem(void);
+static int voice_alloc_oob_mem_table(void);
+static int voice_alloc_and_map_cal_mem(struct voice_data *v);
+static int voice_alloc_and_map_oob_mem(struct voice_data *v);
 
 static struct voice_data *voice_get_session_by_idx(int idx);
 static int voice_get_idx_for_session(u32 session_id);
@@ -1238,6 +1247,89 @@
 	return ret;
 }
 
+int voc_alloc_cal_shared_memory(void)
+{
+	int rc = 0;
+
+	mutex_lock(&common.common_lock);
+	if (is_cal_memory_allocated()) {
+		pr_debug("%s: Calibration shared buffer already allocated",
+			 __func__);
+	} else {
+		/* Allocate memory for calibration memory map table. */
+		rc = voice_alloc_cal_mem_map_table();
+		if (rc < 0) {
+			pr_err("%s: Failed to allocate cal memory, err=%d",
+			       __func__, rc);
+		}
+	}
+	mutex_unlock(&common.common_lock);
+
+	return rc;
+}
+
+int voc_alloc_voip_shared_memory(void)
+{
+	int rc = 0;
+
+	/* Allocate shared memory for OOB Voip */
+	rc = voice_alloc_oob_shared_mem();
+	if (rc < 0) {
+		pr_err("%s: Failed to alloc shared memory for OOB rc:%d\n",
+			   __func__, rc);
+	} else {
+		/* Allocate mem map table for OOB */
+		rc = voice_alloc_oob_mem_table();
+		if (rc < 0) {
+			pr_err("%s: Failed to alloc mem map talbe rc:%d\n",
+			       __func__, rc);
+
+			voice_free_oob_shared_mem();
+		}
+	}
+
+	return rc;
+}
+
+static int is_cal_memory_allocated(void)
+{
+	bool ret;
+
+	if (common.cal_mem_map_table.client != NULL &&
+	    common.cal_mem_map_table.handle != NULL)
+		ret = true;
+	else
+		ret = false;
+
+	return ret;
+}
+
+static int is_voip_memory_allocated(void)
+{
+	bool ret;
+	struct voice_data *v = voice_get_session(
+				common.voice[VOC_PATH_FULL].session_id);
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL, session_id:%d\n", __func__,
+		common.voice[VOC_PATH_FULL].session_id);
+
+		ret = false;
+		goto done;
+	}
+
+	mutex_lock(&common.common_lock);
+	if (v->shmem_info.sh_buf.client != NULL &&
+	    v->shmem_info.sh_buf.handle != NULL)
+		ret = true;
+	else
+		ret = false;
+	mutex_unlock(&common.common_lock);
+
+done:
+	return ret;
+}
+
 static int voice_config_cvs_vocoder(struct voice_data *v)
 {
 	int ret = 0;
@@ -1691,26 +1783,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvs) {
 		pr_err("%s: apr_cvs is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVS cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvs_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1739,7 +1833,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d registering CVS cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvs_wait,
 				 (v->cvs_state == CMD_STATUS_SUCCESS),
@@ -1747,13 +1841,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v)
@@ -1766,18 +1858,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvs) {
 		pr_err("%s: apr_cvs is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvs_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -1795,7 +1895,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d de-registering CVS cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvs_wait,
 				 (v->cvs_state == CMD_STATUS_SUCCESS),
@@ -1803,13 +1903,11 @@
 	if (!ret) {
 		pr_err("%s: Command  timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 
 }
 
@@ -1823,26 +1921,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocproc_dev_cfg_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvp_reg_dev_cfg_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1867,7 +1967,7 @@
 		pr_err("%s: Error %d registering CVP dev cfg cal\n",
 		       __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -1875,13 +1975,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_deregister_dev_cfg_cmd(struct voice_data *v)
@@ -1894,18 +1992,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
-		pr_err("%s: apr_cvp is NULL.\n", __func__);
+		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocproc_dev_cfg_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvp_dereg_dev_cfg_cmd.hdr.hdr_field =
 				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1926,7 +2032,7 @@
 		pr_err("%s: Error %d de-registering CVP dev cfg cal\n",
 		       __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -1934,13 +2040,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_register_cal_cmd(struct voice_data *v)
@@ -1953,26 +2057,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocproc_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvp_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2001,7 +2107,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d registering CVP cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2009,13 +2115,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v)
@@ -2028,18 +2132,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL.\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocproc_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvp_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -2057,7 +2169,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d de-registering CVP cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2065,12 +2177,10 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
+done:
 	return -EINVAL;
 }
 
@@ -2084,26 +2194,28 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
-		pr_err("%s: apr_cvp is NULL.\n", __func__);
+		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.cal_mem_handle) {
-		pr_err("%s: Cal mem handle is NULL\n", __func__);
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	get_vocvol_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP vol cal size is 0\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
 	cvp_reg_vol_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2135,7 +2247,7 @@
 	if (ret < 0) {
 		pr_err("%s: Error %d registering CVP vol cal\n", __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2143,13 +2255,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_send_cvp_deregister_vol_cal_cmd(struct voice_data *v)
@@ -2162,18 +2272,26 @@
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if (!common.apr_q6_cvp) {
 		pr_err("%s: apr_cvp is NULL\n", __func__);
 
-		goto fail;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!common.cal_mem_handle) {
+		pr_debug("%s: Cal mem handle is NULL\n", __func__);
+
+		goto done;
 	}
 
 	get_vocvol_cal(&cal_block);
 	if (cal_block.cal_size == 0)
-		return 0;
+		goto done;
 
 	cvp_dereg_vol_cal_cmd.hdr.hdr_field =
 			APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2194,7 +2312,7 @@
 		pr_err("%s: Error %d de-registering CVP vol cal\n",
 		       __func__, ret);
 
-		goto fail;
+		goto done;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
 				 (v->cvp_state == CMD_STATUS_SUCCESS),
@@ -2202,13 +2320,11 @@
 	if (!ret) {
 		pr_err("%s: Command timeout\n", __func__);
 
-		goto fail;
+		goto done;
 	}
 
-	return 0;
-
-fail:
-	return -EINVAL;
+done:
+	return ret;
 }
 
 static int voice_map_memory_physical_cmd(struct voice_data *v,
@@ -2320,10 +2436,11 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&common.common_lock);
 	if (common.cal_mem_handle != 0) {
 		pr_debug("%s: Cal block already mem mapped\n", __func__);
 
-		return ret;
+		goto done;
 	}
 
 	/* Get the physical address of calibration memory block from ACDB. */
@@ -2332,7 +2449,8 @@
 	if (!cal_block.cal_paddr) {
 		pr_err("%s: Cal block not allocated\n", __func__);
 
-		return -EINVAL;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	ret = voice_map_memory_physical_cmd(v,
@@ -2341,6 +2459,8 @@
 					    cal_block.cal_size,
 					    VOC_CAL_MEM_MAP_TOKEN);
 
+done:
+	mutex_unlock(&common.common_lock);
 	return ret;
 }
 
@@ -2414,7 +2534,6 @@
 	}
 
 	voice_send_cvs_register_cal_cmd(v);
-
 	voice_send_cvp_register_dev_cfg_cmd(v);
 	voice_send_cvp_register_cal_cmd(v);
 	voice_send_cvp_register_vol_cal_cmd(v);
@@ -4157,31 +4276,34 @@
 			goto fail;
 		}
 
-		/* Memory map the calibration memory block. */
-		ret = voice_mem_map_cal_block(v);
+		/* Allocate cal mem if not already allocated and memory map
+		 * the calibration memory block.
+		 */
+		ret = voice_alloc_and_map_cal_mem(v);
 		if (ret < 0) {
-			pr_err("%s: Memory map of cal block failed %d\n",
-			       __func__, ret);
-			/* Allow call to continue, call quality will be bad. */
+			pr_debug("%s: Continue without calibration %d\n",
+				 __func__, ret);
 		}
 
 		if (is_voip_session(session_id)) {
-			ret = voice_map_memory_physical_cmd(v,
-			      &v->shmem_info.memtbl,
-			      v->shmem_info.sh_buf.buf[0].phys,
-			      v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS,
-			      VOIP_MEM_MAP_TOKEN);
-			if (ret) {
-				pr_err("%s: mvm_map_memory_phy failed %d\n",
-					__func__, ret);
+			/* Allocate oob mem if not already allocated and
+			 * memory map the oob memory block.
+			 */
+			ret = voice_alloc_and_map_oob_mem(v);
+			if (ret < 0) {
+				pr_err("%s: voice_alloc_and_map_oob_mem() failed, ret:%d\n",
+				       __func__, ret);
+
 				goto fail;
 			}
+
 			ret = voice_set_packet_exchange_mode_and_config(
 				session_id,
 				VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND);
 			if (ret) {
 				pr_err("%s: Err: exchange_mode_and_config  %d\n",
 					__func__, ret);
+
 				goto fail;
 			}
 		}
@@ -4291,9 +4413,14 @@
 			apr_reset(c->apr_q6_mvm);
 			c->apr_q6_mvm = NULL;
 
+			/* clean up memory handle */
+			c->cal_mem_handle = 0;
+
 			/* Sub-system restart is applicable to all sessions. */
-			for (i = 0; i < MAX_VOC_SESSIONS; i++)
+			for (i = 0; i < MAX_VOC_SESSIONS; i++) {
 				c->voice[i].mvm_handle = 0;
+				c->voice[i].shmem_info.mem_handle = 0;
+			}
 		}
 		return 0;
 	}
@@ -4794,6 +4921,45 @@
 	return 0;
 }
 
+static int voice_free_oob_shared_mem(void)
+{
+	int rc = 0;
+	int cnt = 0;
+	int bufcnt = NUM_OF_BUFFERS;
+	struct voice_data *v = voice_get_session(
+				common.voice[VOC_PATH_FULL].session_id);
+
+	mutex_lock(&common.common_lock);
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		rc = -EINVAL;
+		goto done;
+	}
+
+	rc = msm_audio_ion_free(v->shmem_info.sh_buf.client,
+				v->shmem_info.sh_buf.handle);
+	if (rc < 0) {
+		pr_err("%s: Error:%d freeing memory\n", __func__, rc);
+
+		goto done;
+	}
+
+
+	while (cnt < bufcnt) {
+		v->shmem_info.sh_buf.buf[cnt].data =  NULL;
+		v->shmem_info.sh_buf.buf[cnt].phys =  0;
+		cnt++;
+	}
+
+	v->shmem_info.sh_buf.client = NULL;
+	v->shmem_info.sh_buf.handle = NULL;
+
+done:
+	mutex_unlock(&common.common_lock);
+	return rc;
+}
+
 static int voice_alloc_oob_shared_mem(void)
 {
 	int cnt = 0;
@@ -4806,9 +4972,12 @@
 	struct voice_data *v = voice_get_session(
 				common.voice[VOC_PATH_FULL].session_id);
 
+	mutex_lock(&common.common_lock);
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
+
+		rc = -EINVAL;
+		goto done;
 	}
 
 	rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
@@ -4816,10 +4985,11 @@
 			bufsz*bufcnt,
 			(ion_phys_addr_t *)&phys, (size_t *)&len,
 			&mem_addr);
-	if (rc) {
+	if (rc < 0) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		return -EINVAL;
+
+		goto done;
 	}
 
 	while (cnt < bufcnt) {
@@ -4842,7 +5012,9 @@
 
 	memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
 
-	return 0;
+done:
+	mutex_unlock(&common.common_lock);
+	return rc;
 }
 
 static int voice_alloc_oob_mem_table(void)
@@ -4852,9 +5024,12 @@
 	struct voice_data *v = voice_get_session(
 				common.voice[VOC_PATH_FULL].session_id);
 
+	mutex_lock(&common.common_lock);
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
+
+		rc = -EINVAL;
+		goto done;
 	}
 
 	rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
@@ -4863,21 +5038,22 @@
 				(ion_phys_addr_t *)&v->shmem_info.memtbl.phys,
 				(size_t *)&len,
 				&(v->shmem_info.memtbl.data));
-	if (rc) {
+	if (rc < 0) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		return -EINVAL;
+
+		goto done;
 	}
 
 	v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
-
 	pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
 		 (void *)v->shmem_info.memtbl.data,
 		 (void *)v->shmem_info.memtbl.phys,
 		 (void *)&v->shmem_info.memtbl.phys);
 
-	return 0;
-
+done:
+	mutex_unlock(&common.common_lock);
+	return rc;
 }
 
 static int voice_alloc_cal_mem_map_table(void)
@@ -4885,17 +5061,17 @@
 	int ret = 0;
 	int len;
 
-	ret = msm_audio_ion_alloc("voip_client",
+	ret = msm_audio_ion_alloc("voc_cal",
 				&(common.cal_mem_map_table.client),
 				&(common.cal_mem_map_table.handle),
 				sizeof(struct vss_imemory_table_t),
 			      (ion_phys_addr_t *)&common.cal_mem_map_table.phys,
 				(size_t *) &len,
 				&(common.cal_mem_map_table.data));
-	if (ret) {
+	if (ret < 0) {
 		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, ret);
-		return -EINVAL;
+		goto done;
 	}
 
 	common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
@@ -4903,7 +5079,78 @@
 		 (unsigned int) common.cal_mem_map_table.data,
 		 common.cal_mem_map_table.phys);
 
-	return 0;
+done:
+	return ret;
+}
+
+static int voice_alloc_and_map_cal_mem(struct voice_data *v)
+{
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		return -EINVAL;
+	}
+
+	ret = voc_alloc_cal_shared_memory();
+	if (ret < 0) {
+		pr_err("%s: Memory allocation of cal block failed %d\n",
+			   __func__, ret);
+
+		goto done;
+	}
+
+	/* Memory map the calibration memory block. */
+	ret = voice_mem_map_cal_block(v);
+	if (ret < 0) {
+		pr_err("%s: Memory map of cal block failed %d\n",
+			   __func__, ret);
+	}
+
+done:
+	return ret;
+}
+
+static int voice_alloc_and_map_oob_mem(struct voice_data *v)
+{
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		return -EINVAL;
+	}
+
+	if (!is_voip_memory_allocated()) {
+		ret = voc_alloc_voip_shared_memory();
+		if (ret < 0) {
+			pr_err("%s: Failed to create voip oob memory %d\n",
+				   __func__, ret);
+
+			goto done;
+		}
+	}
+
+	ret = voice_map_memory_physical_cmd(v,
+			&v->shmem_info.memtbl,
+			v->shmem_info.sh_buf.buf[0].phys,
+			v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS,
+			VOIP_MEM_MAP_TOKEN);
+	if (ret) {
+		pr_err("%s: mvm_map_memory_phy failed %d\n",
+			   __func__, ret);
+
+		goto done;
+	}
+
+done:
+	return ret;
+}
+
+int is_voc_initialized(void)
+{
+	return module_initialized;
 }
 
 static int __init voice_init(void)
@@ -4949,21 +5196,11 @@
 		mutex_init(&common.voice[i].lock);
 	}
 
-	/* Allocate shared memory for OOB Voip */
-	rc = voice_alloc_oob_shared_mem();
-	if (rc < 0)
-		pr_err("failed to alloc shared memory for OOB %d\n", rc);
-	else {
-		/* Allocate mem map table for OOB */
-		rc = voice_alloc_oob_mem_table();
-		if (rc < 0)
-			pr_err("failed to alloc mem map talbe %d\n", rc);
-	}
+	if (rc == 0)
+		module_initialized = true;
 
-	/* Allocate memory for calibration memory map table. */
-	rc = voice_alloc_cal_mem_map_table();
-
+	pr_debug("%s: rc=%d\n", __func__, rc);
 	return rc;
 }
 
-late_initcall(voice_init);
+device_initcall(voice_init);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 52cf940..b8f7008 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1374,6 +1374,9 @@
 uint8_t voc_get_route_flag(uint32_t session_id, uint8_t path_dir);
 int voc_enable_dtmf_rx_detection(uint32_t session_id, uint32_t enable);
 void voc_disable_dtmf_det_on_active_sessions(void);
+int voc_alloc_cal_shared_memory(void);
+int voc_alloc_voip_shared_memory(void);
+int is_voc_initialized(void);
 
 uint32_t voc_get_session_id(char *name);