Merge "msm: vidc: Add support to send max num B frames"
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
index ac8ea73..4cbff52 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -16,6 +16,7 @@
 - qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
 - qcom,gpio-err-fatal: GPIO used by the lpass to indicate error fatal to the apps.
 - qcom,gpio-force-stop: GPIO used by the apps to force the lpass to shutdown.
+- qcom,gpio-proxy-unvote: GPIO used by the lpass to indicate apps clock is ready.
 
 Optional properties:
 - vdd_pll-supply:     Reference to the regulator that supplies the PLL's rail.
@@ -32,8 +33,9 @@
 		vdd_cx-supply = <&pm8841_s2>;
 	        qcom,firmware-name = "lpass";
 
-		/* GPIO input from lpass */
+		/* GPIO inputs from lpass */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
 
 		/* GPIO output to lpass */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index fe4cada..b88b991 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -29,16 +29,18 @@
 			#size-cells = <1>;
 			status = "disabled";
 
-			qcom,chg-vddmax-mv = <4200>;
-			qcom,chg-vddsafe-mv = <4200>;
-			qcom,chg-vinmin-mv = <4200>;
-			qcom,chg-vbatdet-mv = <4100>;
-			qcom,chg-ibatmax-ma = <1500>;
-			qcom,chg-ibatterm-ma = <200>;
-			qcom,chg-ibatsafe-ma = <1500>;
-			qcom,chg-thermal-mitigation = <1500 700 600 325>;
+			qcom,vddmax-mv = <4200>;
+			qcom,vddsafe-mv = <4200>;
+			qcom,vinmin-mv = <4200>;
+			qcom,vbatdet-mv = <4100>;
+			qcom,ibatmax-ma = <1500>;
+			qcom,ibatterm-ma = <200>;
+			qcom,ibatsafe-ma = <1500>;
+			qcom,thermal-mitigation = <1500 700 600 325>;
+			qcom,vbatdet-delta-mv = <350>;
+			qcom,tchg-mins = <150>;
 
-			qcom,chg-chgr@1000 {
+			qcom,chgr@1000 {
 				status = "disabled";
 				reg = <0x1000 0x100>;
 				interrupts =	<0x0 0x10 0x0>,
@@ -60,7 +62,7 @@
 							"chg-done";
 			};
 
-			qcom,chg-buck@1100 {
+			qcom,buck@1100 {
 				status = "disabled";
 				reg = <0x1100 0x100>;
 				interrupts =	<0x0 0x11 0x0>,
@@ -80,7 +82,7 @@
 							"vdd-loop";
 			};
 
-			qcom,chg-bat-if@1200 {
+			qcom,bat-if@1200 {
 				status = "disabled";
 				reg = <0x1200 0x100>;
 				interrupts =	<0x0 0x12 0x0>,
@@ -96,7 +98,7 @@
 							"psi";
 			};
 
-			qcom,chg-usb-chgpth@1300 {
+			qcom,usb-chgpth@1300 {
 				status = "disabled";
 				reg = <0x1300 0x100>;
 				interrupts =	<0 0x13 0x0>,
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index b949d3b..eff4fae 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -756,8 +756,9 @@
 
 		qcom,firmware-name = "adsp";
 
-		/* GPIO input from lpass */
+		/* GPIO inputs from lpass */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
 
 		/* GPIO output to lpass */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index a8a2446..9b114cc 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -17,7 +17,8 @@
 / {
 	model = "Qualcomm MSM 8610 CDP";
 	compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
-	qcom,msm-id = <147 1 0>, <165 1 0>;
+	qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
+		      <163 1 0>, <164 1 0>, <166 1 0>;
 
 	serial@f991e000 {
 		status = "ok";
@@ -100,18 +101,18 @@
 
 &pm8110_chg {
 	status = "ok";
-	qcom,chg-charging-disabled;
-	qcom,chg-use-default-batt-values;
+	qcom,charging-disabled;
+	qcom,use-default-batt-values;
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index b1511ff..e416105 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -17,7 +17,8 @@
 / {
 	model = "Qualcomm MSM 8610 MTP";
 	compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
-	qcom,msm-id = <147 8 0>, <165 8 0>;
+	qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
+		      <163 8 0>, <164 8 0>, <166 8 0>;
 
 	serial@f991f000 {
 		status = "ok";
@@ -100,21 +101,21 @@
 
 &pm8110_chg {
 	status = "ok";
-	qcom,chg-charging-disabled;
+	qcom,charging-disabled;
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-bat-if@1200 {
+	qcom,bat-if@1200 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index b6a4315..aab1037 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -640,8 +640,9 @@
 		vdd_cx-supply = <&pm8110_s1_corner>;
 		qcom,firmware-name = "adsp";
 
-		/* GPIO input from lpass */
+		/* GPIO inputs from lpass */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
 
 		/* GPIO output to lpass */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index df0db7e..b574a31 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -111,7 +111,7 @@
 		reg = <0x6c 0x0>;
 		qcom,slave-id = <0x6c 0x300A 0x2720>;
 		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <0>;
+		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index f58c1e2..748d5f7 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -112,7 +112,7 @@
 		reg = <0x6c>;
 		qcom,slave-id = <0x6c 0x300A 0x2720>;
 		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <0>;
+		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 767a705..53f6e9e 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -113,7 +113,7 @@
 		reg = <0x6c>;
 		qcom,slave-id = <0x6c 0x300A 0x2720>;
 		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <0>;
+		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 3a78a15..94a28f7 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -23,8 +23,9 @@
 	qcom,csiphy@fda0ac00 {
 		cell-index = <0>;
 		compatible = "qcom,csiphy";
-		reg = <0xfda0ac00 0x200>;
-		reg-names = "csiphy";
+		reg = <0xfda0ac00 0x200>,
+                      <0xfda00030 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
 		interrupts = <0 78 0>;
 		interrupt-names = "csiphy";
 	};
@@ -32,8 +33,9 @@
 	qcom,csiphy@fda0b000 {
 		cell-index = <1>;
 		compatible = "qcom,csiphy";
-		reg = <0xfda0b000 0x200>;
-		reg-names = "csiphy";
+		reg = <0xfda0b000 0x200>,
+                      <0xfda00038 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
 		interrupts = <0 79 0>;
 		interrupt-names = "csiphy";
 	};
@@ -41,8 +43,9 @@
 	qcom,csiphy@fda0b400 {
 		cell-index = <2>;
 		compatible = "qcom,csiphy";
-		reg = <0xfda0b400 0x200>;
-		reg-names = "csiphy";
+		reg = <0xfda0b400 0x200>,
+                      <0xfda00040 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
 		interrupts = <0 80 0>;
 		interrupt-names = "csiphy";
 	};
@@ -94,8 +97,9 @@
 	qcom,ispif@fda0A000 {
 		cell-index = <0>;
 		compatible = "qcom,ispif";
-		reg = <0xfda0A000 0x500>;
-		reg-names = "ispif";
+		reg = <0xfda0A000 0x500>,
+                      <0xfda00020 0x10>;
+		reg-names = "ispif", "csi_clk_mux";
 		interrupts = <0 55 0>;
 		interrupt-names = "ispif";
 	};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index a9685cc..86baab2 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -834,8 +834,9 @@
 
 		qcom,firmware-name = "adsp";
 
-		/* GPIO input from lpass */
+		/* GPIO inputs from lpass */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
 
 		/* GPIO output to lpass */
 		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index aa2c028..e7a6cf0 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -239,6 +239,7 @@
 CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_TSPP=m
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_QSEECOM=y
 CONFIG_QPNP_MISC=y
@@ -321,6 +322,7 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_DVB_CORE=m
 # CONFIG_MSM_CAMERA is not set
 CONFIG_MT9M114=y
 CONFIG_OV2720=y
@@ -338,6 +340,8 @@
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index c9f068a..bbfcad9 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -85,6 +85,7 @@
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_UARTDM_Core_v14=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 2de8799..707e6b6 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4947,68 +4947,75 @@
 		"fda0b400.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_clk", camss_phy2_csi2phytimer_clk.c,
 		"fda0b400.qcom,csiphy"),
+
 	/* CSID clocks */
-	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
-		"fda08000.qcom,csid"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
-		"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c, "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08000.qcom,csid"),
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", camss_csi0_ahb_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_src_clk", csi0_clk_src.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_phy_clk", camss_csi0phy_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_clk", camss_csi0_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_pix_clk", camss_csi0pix_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_clk", camss_csi0rdi_clk.c,
+					"fda08000.qcom,csid"),
 
-	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
-		"fda08400.qcom,csid"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
-		"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_ahb_clk", camss_csi1_ahb_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_src_clk", csi1_clk_src.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_phy_clk", camss_csi1phy_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_clk", camss_csi1_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_pix_clk", camss_csi1pix_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_rdi_clk", camss_csi1rdi_clk.c, "fda08400.qcom,csid"),
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", camss_csi1_ahb_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_src_clk", csi1_clk_src.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_phy_clk", camss_csi1phy_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_clk", camss_csi1_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_pix_clk", camss_csi1pix_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_clk", camss_csi1rdi_clk.c,
+					"fda08400.qcom,csid"),
 
-	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
-		"fda08800.qcom,csid"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
-		"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi2_ahb_clk", camss_csi2_ahb_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi2_src_clk", csi2_clk_src.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi2_phy_clk", camss_csi2phy_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi2_clk", camss_csi2_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi2_pix_clk", camss_csi2pix_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08800.qcom,csid"),
-	CLK_LOOKUP("csi2_rdi_clk", camss_csi2rdi_clk.c, "fda08800.qcom,csid"),
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", camss_csi2_ahb_clk.c,
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("csi_src_clk", csi2_clk_src.c,
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("csi_phy_clk", camss_csi2phy_clk.c,
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("csi_clk", camss_csi2_clk.c,
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("csi_pix_clk", camss_csi2pix_clk.c,
+					"fda08800.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_clk", camss_csi2rdi_clk.c,
+					"fda08800.qcom,csid"),
 
-	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
-		"fda08c00.qcom,csid"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
-		"fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi3_ahb_clk", camss_csi3_ahb_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi3_src_clk", csi3_clk_src.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi3_phy_clk", camss_csi3phy_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi3_clk", camss_csi3_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi3_pix_clk", camss_csi3pix_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi3_rdi_clk", camss_csi3rdi_clk.c, "fda08c00.qcom,csid"),
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", camss_csi3_ahb_clk.c,
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi_src_clk", csi3_clk_src.c,
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi_phy_clk", camss_csi3phy_clk.c,
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi_clk", camss_csi3_clk.c,
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi_pix_clk", camss_csi3pix_clk.c,
+					"fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_clk", camss_csi3rdi_clk.c,
+					"fda08c00.qcom,csid"),
 
 	/* ISPIF clocks */
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 72f5051..6110ee7 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -653,7 +653,7 @@
 void msm_snddev_tx_route_config(void);
 void msm_snddev_tx_route_deconfig(void);
 
-extern unsigned int msm_shared_ram_phys; /* defined in arch/arm/mach-msm/io.c */
+extern phys_addr_t msm_shared_ram_phys; /* defined in arch/arm/mach-msm/io.c */
 
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index d983ce5..81a6399 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -256,6 +256,18 @@
 int smsm_check_for_modem_crash(void);
 void *smem_find(unsigned id, unsigned size);
 void *smem_get_entry(unsigned id, unsigned *size);
+
+/**
+ * smem_virt_to_phys() - Convert SMEM address to physical address.
+ *
+ * @smem_address: Virtual address returned by smem_alloc()/smem_alloc2()
+ * @returns: Physical address (or NULL if there is a failure)
+ *
+ * This function should only be used if an SMEM item needs to be handed
+ * off to a DMA engine.
+ */
+phys_addr_t smem_virt_to_phys(void *smem_address);
+
 #else
 static inline void *smem_alloc(unsigned id, unsigned size)
 {
@@ -339,5 +351,9 @@
 {
 	return NULL;
 }
+static inline phys_addr_t smem_virt_to_phys(void *smem_address)
+{
+	return NULL;
+}
 #endif
 #endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index ecac4a5..65a5afb 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -45,7 +45,7 @@
 /* msm_shared_ram_phys default value of 0x00100000 is the most common value
  * and should work as-is for any target without stacked memory.
  */
-unsigned int msm_shared_ram_phys = 0x00100000;
+phys_addr_t msm_shared_ram_phys = 0x00100000;
 
 static void __init msm_map_io(struct map_desc *io_desc, int size)
 {
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 608c5e0..277addc 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -391,7 +391,7 @@
 	struct q6v5_data *q6;
 	struct pil_desc *desc;
 	struct resource *res;
-	int ret;
+	int ret, gpio_clk_ready;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
@@ -408,6 +408,12 @@
 		return ret;
 	drv->err_fatal_irq = ret;
 
+	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
+					    "qcom,gpio-proxy-unvote", 0));
+	if (ret < 0)
+		return ret;
+	gpio_clk_ready = ret;
+
 	drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
 						"qcom,gpio-force-stop", 0);
 	if (drv->force_stop_gpio < 0)
@@ -421,6 +427,7 @@
 	desc = &q6->desc;
 	desc->owner = THIS_MODULE;
 	desc->proxy_timeout = PROXY_TIMEOUT_MS;
+	desc->proxy_unvote_irq = gpio_clk_ready;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
 	q6->restart_reg = devm_request_and_ioremap(&pdev->dev, res);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index a213112..3590e6b 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -34,7 +34,6 @@
 #include <linux/kfifo.h>
 #include <linux/wakelock.h>
 #include <linux/notifier.h>
-#include <linux/sort.h>
 #include <linux/suspend.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -47,6 +46,7 @@
 #include <mach/proc_comm.h>
 #include <mach/msm_ipc_logging.h>
 #include <mach/ramdump.h>
+#include <mach/board.h>
 
 #include <asm/cacheflush.h>
 
@@ -184,7 +184,7 @@
 static struct smem_area *smem_areas;
 static struct ramdump_segment *smem_ramdump_segments;
 static void *smem_ramdump_dev;
-static void *smem_range_check(phys_addr_t base, unsigned offset);
+static void *smem_phys_to_virt(phys_addr_t base, unsigned offset);
 static void *smd_dev;
 
 struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
@@ -244,6 +244,17 @@
 #define SMx_POWER_INFO(x...) do { } while (0)
 #endif
 
+/**
+ * OVERFLOW_ADD_UNSIGNED() - check for unsigned overflow
+ *
+ * @type: type to check for overflow
+ * @a: left value to use
+ * @b: right value to use
+ * @returns: true if a + b will result in overflow; false otherwise
+ */
+#define OVERFLOW_ADD_UNSIGNED(type, a, b) \
+	(((type)~0 - (a)) < (b) ? true : false)
+
 static unsigned last_heap_free = 0xffffffff;
 
 static inline void smd_write_intr(unsigned int val,
@@ -2400,37 +2411,107 @@
 
 /* -------------------------------------------------------------------------- */
 
-/*
- * Shared Memory Range Check
- *
- * Takes a physical address and an offset and checks if the resulting physical
- * address would fit into one of the aux smem regions.  If so, returns the
- * corresponding virtual address.  Otherwise returns NULL.  Expects the array
- * of smem regions to be in ascending physical address order.
+/**
+ * smem_phys_to_virt() - Convert a physical base and offset to virtual address
  *
  * @base: physical base address to check
  * @offset: offset from the base to get the final address
+ * @returns: virtual SMEM address; NULL for failure
+ *
+ * Takes a physical address and an offset and checks if the resulting physical
+ * address would fit into one of the smem regions.  If so, returns the
+ * corresponding virtual address.  Otherwise returns NULL.
  */
-static void *smem_range_check(phys_addr_t base, unsigned offset)
+static void *smem_phys_to_virt(phys_addr_t base, unsigned offset)
 {
 	int i;
 	phys_addr_t phys_addr;
 	resource_size_t size;
 
+	if (OVERFLOW_ADD_UNSIGNED(phys_addr_t, base, offset))
+		return NULL;
+
+	if (!smem_areas) {
+		/*
+		 * Early boot - no area configuration yet, so default
+		 * to using the main memory region.
+		 *
+		 * To remove the MSM_SHARED_RAM_BASE and the static
+		 * mapping of SMEM in the future, add dump_stack()
+		 * to identify the early callers of smem_get_entry()
+		 * (which calls this function) and replace those calls
+		 * with a new function that knows how to lookup the
+		 * SMEM base address before SMEM has been probed.
+		 */
+		phys_addr = msm_shared_ram_phys;
+		size = MSM_SHARED_RAM_SIZE;
+
+		if (base >= phys_addr && base + offset < phys_addr + size) {
+			if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
+				(uintptr_t)MSM_SHARED_RAM_BASE, offset)) {
+				pr_err("%s: overflow %p %x\n", __func__,
+					MSM_SHARED_RAM_BASE, offset);
+				return NULL;
+			}
+
+			return MSM_SHARED_RAM_BASE + offset;
+		} else {
+			return NULL;
+		}
+	}
 	for (i = 0; i < num_smem_areas; ++i) {
 		phys_addr = smem_areas[i].phys_addr;
 		size = smem_areas[i].size;
-		if (base < phys_addr)
-			return NULL;
-		if (base > phys_addr + size)
+
+		if (base < phys_addr || base + offset >= phys_addr + size)
 			continue;
-		if (base >= phys_addr && base + offset < phys_addr + size)
-			return smem_areas[i].virt_addr + offset;
+
+		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
+				(uintptr_t)smem_areas[i].virt_addr, offset)) {
+			pr_err("%s: overflow %p %x\n", __func__,
+				smem_areas[i].virt_addr, offset);
+			return NULL;
+		}
+
+		return smem_areas[i].virt_addr + offset;
 	}
 
 	return NULL;
 }
 
+/**
+ * smem_virt_to_phys() - Convert SMEM address to physical address.
+ *
+ * @smem_address: Address of SMEM item (returned by smem_alloc(), etc)
+ * @returns: Physical address (or NULL if there is a failure)
+ *
+ * This function should only be used if an SMEM item needs to be handed
+ * off to a DMA engine.
+ */
+phys_addr_t smem_virt_to_phys(void *smem_address)
+{
+	phys_addr_t phys_addr = 0;
+	int i;
+	void *vend;
+
+	if (!smem_areas)
+		return phys_addr;
+
+	for (i = 0; i < num_smem_areas; ++i) {
+		vend = (void *)(smem_areas[i].virt_addr + smem_areas[i].size);
+
+		if (smem_address >= smem_areas[i].virt_addr &&
+				smem_address < vend) {
+			phys_addr = smem_address - smem_areas[i].virt_addr;
+			phys_addr +=  smem_areas[i].phys_addr;
+			break;
+		}
+	}
+
+	return phys_addr;
+}
+EXPORT_SYMBOL(smem_virt_to_phys);
+
 /* smem_alloc returns the pointer to smem item if it is already allocated.
  * Otherwise, it returns NULL.
  */
@@ -2504,14 +2585,15 @@
 		remote_spin_lock_irqsave(&remote_spinlock, flags);
 	/* toc is in device memory and cannot be speculatively accessed */
 	if (toc[id].allocated) {
+		phys_addr_t phys_base;
+
 		*size = toc[id].size;
 		barrier();
-		if (!(toc[id].reserved & BASE_ADDR_MASK))
-			ret = (void *) (MSM_SHARED_RAM_BASE + toc[id].offset);
-		else
-			ret = smem_range_check(
-				toc[id].reserved & BASE_ADDR_MASK,
-				toc[id].offset);
+
+		phys_base = toc[id].reserved & BASE_ADDR_MASK;
+		if (!phys_base)
+			phys_base = (phys_addr_t)msm_shared_ram_phys;
+		ret = smem_phys_to_virt(phys_base, toc[id].offset);
 	} else {
 		*size = 0;
 	}
@@ -3464,14 +3546,6 @@
 	return ret;
 }
 
-int sort_cmp_func(const void *a, const void *b)
-{
-	struct smem_area *left = (struct smem_area *)(a);
-	struct smem_area *right = (struct smem_area *)(b);
-
-	return left->phys_addr - right->phys_addr;
-}
-
 int smd_core_platform_init(struct platform_device *pdev)
 {
 	int i;
@@ -3482,7 +3556,8 @@
 	struct smd_subsystem_config *cfg;
 	int err_ret = 0;
 	struct smd_smem_regions *smd_smem_areas;
-	int smem_idx = 0;
+	struct smem_area *smem_areas_tmp = NULL;
+	int smem_idx;
 
 	smd_platform_data = pdev->dev.platform_data;
 	num_ss = smd_platform_data->num_ss_configs;
@@ -3493,37 +3568,54 @@
 			   smd_ssr_config->disable_smsm_reset_handshake;
 
 	smd_smem_areas = smd_platform_data->smd_smem_areas;
-	if (smd_smem_areas) {
-		num_smem_areas = smd_platform_data->num_smem_areas;
-		smem_areas = kmalloc(sizeof(struct smem_area) * num_smem_areas,
-						GFP_KERNEL);
-		if (!smem_areas) {
-			pr_err("%s: smem_areas kmalloc failed\n", __func__);
+	num_smem_areas = smd_platform_data->num_smem_areas + 1;
+
+	/* Initialize main SMEM region */
+	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
+				GFP_KERNEL);
+	if (!smem_areas_tmp) {
+		pr_err("%s: smem_areas kmalloc failed\n", __func__);
+		err_ret = -ENOMEM;
+		goto smem_areas_alloc_fail;
+	}
+
+	smem_areas_tmp[0].phys_addr =  msm_shared_ram_phys;
+	smem_areas_tmp[0].size = MSM_SHARED_RAM_SIZE;
+	smem_areas_tmp[0].virt_addr = MSM_SHARED_RAM_BASE;
+
+	/* Configure auxiliary SMEM regions */
+	for (smem_idx = 1; smem_idx < num_smem_areas; ++smem_idx) {
+		smem_areas_tmp[smem_idx].phys_addr =
+				smd_smem_areas[smem_idx].phys_addr;
+		smem_areas_tmp[smem_idx].size =
+				smd_smem_areas[smem_idx].size;
+		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
+			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
+			smem_areas_tmp[smem_idx].size);
+		if (!smem_areas_tmp[smem_idx].virt_addr) {
+			pr_err("%s: ioremap_nocache() of addr: %pa size: %pa\n",
+				__func__,
+				&smem_areas_tmp[smem_idx].phys_addr,
+				&smem_areas_tmp[smem_idx].size);
 			err_ret = -ENOMEM;
-			goto smem_areas_alloc_fail;
+			goto smem_failed;
 		}
 
-		for (smem_idx = 0; smem_idx < num_smem_areas; ++smem_idx) {
-			smem_areas[smem_idx].phys_addr =
-					smd_smem_areas[smem_idx].phys_addr;
-			smem_areas[smem_idx].size =
-					smd_smem_areas[smem_idx].size;
-			smem_areas[smem_idx].virt_addr = ioremap_nocache(
-				(unsigned long)(smem_areas[smem_idx].phys_addr),
-				smem_areas[smem_idx].size);
-			if (!smem_areas[smem_idx].virt_addr) {
-				pr_err("%s: ioremap_nocache() of addr: %pa size: %pa\n",
-					__func__,
-					&smem_areas[smem_idx].phys_addr,
-					&smem_areas[smem_idx].size);
-				err_ret = -ENOMEM;
-				++smem_idx;
-				goto smem_failed;
-			}
+		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
+				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
+				smem_areas_tmp[smem_idx].size)) {
+			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
+					__func__, smem_idx,
+					smem_areas_tmp[smem_idx].virt_addr,
+					&smem_areas_tmp[smem_idx].size);
+			++smem_idx;
+			err_ret = -EINVAL;
+			goto smem_failed;
 		}
-		sort(smem_areas, num_smem_areas,
-				sizeof(struct smem_area),
-				sort_cmp_func, NULL);
+
+		SMD_DBG("%s: %d = %pa %pa", __func__, smem_idx,
+				&smd_smem_areas[smem_idx].phys_addr,
+				&smd_smem_areas[smem_idx].size);
 	}
 
 	for (i = 0; i < num_ss; i++) {
@@ -3567,8 +3659,9 @@
 				cfg->subsys_name, SMD_MAX_CH_NAME_LEN);
 	}
 
-
 	SMD_INFO("smd_core_platform_init() done\n");
+
+	smem_areas = smem_areas_tmp;
 	return 0;
 
 intr_failed:
@@ -3586,9 +3679,12 @@
 				);
 	}
 smem_failed:
-	for (smem_idx = smem_idx - 1; smem_idx >= 0; --smem_idx)
-		iounmap(smem_areas[smem_idx].virt_addr);
-	kfree(smem_areas);
+	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
+		iounmap(smem_areas_tmp[smem_idx].virt_addr);
+
+	num_smem_areas = 0;
+	kfree(smem_areas_tmp);
+
 smem_areas_alloc_fail:
 	return err_ret;
 }
@@ -3762,12 +3858,14 @@
 	resource_size_t aux_mem_size;
 	int temp_string_size = 11; /* max 3 digit count */
 	char temp_string[temp_string_size];
-	int count;
 	struct device_node *node;
 	int ret;
 	const char *compatible;
-	struct ramdump_segment *ramdump_segments_tmp;
+	struct ramdump_segment *ramdump_segments_tmp = NULL;
+	struct smem_area *smem_areas_tmp = NULL;
+	int smem_idx = 0;
 	int subnode_num = 0;
+	int i;
 	resource_size_t irq_out_size;
 
 	disable_smsm_reset_handshake = 1;
@@ -3787,97 +3885,105 @@
 	}
 	SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
 
-	count = 1;
+	num_smem_areas = 1;
 	while (1) {
-		scnprintf(temp_string, temp_string_size, "aux-mem%d", count);
+		scnprintf(temp_string, temp_string_size, "aux-mem%d",
+				num_smem_areas);
 		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 								temp_string);
 		if (!r)
 			break;
 
 		++num_smem_areas;
-		++count;
-		if (count > 999) {
+		if (num_smem_areas > 999) {
 			pr_err("%s: max num aux mem regions reached\n",
 								__func__);
 			break;
 		}
 	}
 
-	/* initialize SSR ramdump regions */
+	/* Initialize main SMEM region and SSR ramdump region */
 	key = "smem";
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
 	if (!r) {
 		pr_err("%s: missing '%s'\n", __func__, key);
 		return -ENODEV;
 	}
-	ramdump_segments_tmp = kmalloc_array(num_smem_areas + 1,
-			sizeof(struct ramdump_segment), GFP_KERNEL);
 
+	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
+				GFP_KERNEL);
+	if (!smem_areas_tmp) {
+		pr_err("%s: smem areas kmalloc failed\n", __func__);
+		ret = -ENOMEM;
+		goto free_smem_areas;
+	}
+
+	ramdump_segments_tmp = kmalloc_array(num_smem_areas,
+			sizeof(struct ramdump_segment), GFP_KERNEL);
 	if (!ramdump_segments_tmp) {
 		pr_err("%s: ramdump segment kmalloc failed\n", __func__);
 		ret = -ENOMEM;
 		goto free_smem_areas;
 	}
-	ramdump_segments_tmp[0].address = r->start;
-	ramdump_segments_tmp[0].size = resource_size(r);
 
-	if (num_smem_areas) {
+	smem_areas_tmp[smem_idx].phys_addr =  r->start;
+	smem_areas_tmp[smem_idx].size = resource_size(r);
+	smem_areas_tmp[smem_idx].virt_addr = MSM_SHARED_RAM_BASE;
 
-		smem_areas = kmalloc(sizeof(struct smem_area) * num_smem_areas,
-					GFP_KERNEL);
+	ramdump_segments_tmp[smem_idx].address = r->start;
+	ramdump_segments_tmp[smem_idx].size = resource_size(r);
+	++smem_idx;
 
-		if (!smem_areas) {
-			pr_err("%s: smem areas kmalloc failed\n", __func__);
+	/* Configure auxiliary SMEM regions */
+	while (1) {
+		scnprintf(temp_string, temp_string_size, "aux-mem%d",
+								smem_idx);
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							temp_string);
+		if (!r)
+			break;
+		aux_mem_base = r->start;
+		aux_mem_size = resource_size(r);
+
+		ramdump_segments_tmp[smem_idx].address = aux_mem_base;
+		ramdump_segments_tmp[smem_idx].size = aux_mem_size;
+
+		smem_areas_tmp[smem_idx].phys_addr = aux_mem_base;
+		smem_areas_tmp[smem_idx].size = aux_mem_size;
+		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
+			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
+			smem_areas_tmp[smem_idx].size);
+		SMD_DBG("%s: %s = %pa %pa -> %p", __func__, temp_string,
+				&aux_mem_base, &aux_mem_size,
+				smem_areas_tmp[smem_idx].virt_addr);
+
+		if (!smem_areas_tmp[smem_idx].virt_addr) {
+			pr_err("%s: ioremap_nocache() of addr:%pa size: %pa\n",
+				__func__,
+				&smem_areas_tmp[smem_idx].phys_addr,
+				&smem_areas_tmp[smem_idx].size);
 			ret = -ENOMEM;
 			goto free_smem_areas;
 		}
-		count = 1;
-		while (1) {
-			scnprintf(temp_string, temp_string_size, "aux-mem%d",
-									count);
-			r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-								temp_string);
-			if (!r)
-				break;
-			aux_mem_base = r->start;
-			aux_mem_size = resource_size(r);
 
-			/*
-			 * Add to ram-dumps segments.
-			 * ramdump_segments_tmp[0] is the main SMEM region,
-			 * so auxiliary segments are indexed by count
-			 * instead of count - 1.
-			 */
-			ramdump_segments_tmp[count].address = aux_mem_base;
-			ramdump_segments_tmp[count].size = aux_mem_size;
-
-			SMD_DBG("%s: %s = %pa %pa", __func__, temp_string,
-					&aux_mem_base, &aux_mem_size);
-			smem_areas[count - 1].phys_addr = aux_mem_base;
-			smem_areas[count - 1].size = aux_mem_size;
-			smem_areas[count - 1].virt_addr = ioremap_nocache(
-				(unsigned long)(smem_areas[count-1].phys_addr),
-				smem_areas[count - 1].size);
-			if (!smem_areas[count - 1].virt_addr) {
-				pr_err("%s: ioremap_nocache() of addr:%pa size: %pa\n",
-					__func__,
-					&smem_areas[count - 1].phys_addr,
-					&smem_areas[count - 1].size);
-				ret = -ENOMEM;
-				goto free_smem_areas;
-			}
-
-			++count;
-			if (count > 999) {
-				pr_err("%s: max num aux mem regions reached\n",
-								__func__);
-				break;
-			}
+		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
+				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
+				smem_areas_tmp[smem_idx].size)) {
+			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
+					__func__, smem_idx,
+					smem_areas_tmp[smem_idx].virt_addr,
+					&smem_areas_tmp[smem_idx].size);
+			++smem_idx;
+			ret = -EINVAL;
+			goto free_smem_areas;
 		}
-		sort(smem_areas, num_smem_areas,
-				sizeof(struct smem_area),
-				sort_cmp_func, NULL);
+
+		++smem_idx;
+		if (smem_idx > 999) {
+			pr_err("%s: max num aux mem regions reached\n",
+							__func__);
+			break;
+		}
 	}
 
 	for_each_child_of_node(pdev->dev.of_node, node) {
@@ -3905,15 +4011,16 @@
 		++subnode_num;
 	}
 
+	smem_areas = smem_areas_tmp;
 	smem_ramdump_segments = ramdump_segments_tmp;
 	return 0;
 
 rollback_subnodes:
-	count = 0;
+	i = 0;
 	for_each_child_of_node(pdev->dev.of_node, node) {
-		if (count >= subnode_num)
+		if (i >= subnode_num)
 			break;
-		++count;
+		++i;
 		compatible = of_get_property(node, "compatible", NULL);
 		if (!strcmp(compatible, "qcom,smd"))
 			unparse_smd_devicetree(node);
@@ -3921,10 +4028,12 @@
 			unparse_smsm_devicetree(node);
 	}
 free_smem_areas:
+	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
+		iounmap(smem_areas_tmp[smem_idx].virt_addr);
+
 	num_smem_areas = 0;
 	kfree(ramdump_segments_tmp);
-	kfree(smem_areas);
-	smem_areas = NULL;
+	kfree(smem_areas_tmp);
 	return ret;
 }
 
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 83f7a1d..84aa455 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -328,7 +328,12 @@
 
 	/* 8610 IDs */
 	[147] = MSM_CPU_8610,
+	[161] = MSM_CPU_8610,
+	[162] = MSM_CPU_8610,
+	[163] = MSM_CPU_8610,
+	[164] = MSM_CPU_8610,
 	[165] = MSM_CPU_8610,
+	[166] = MSM_CPU_8610,
 
 	/* 8064AB IDs */
 	[153] = MSM_CPU_8064AB,
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 6d28042..682d876 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1090,6 +1090,12 @@
 		diag_smd_destructor(&driver->smd_dci[i]);
 
 	platform_driver_unregister(&msm_diag_dci_driver);
+
+	if (driver->dci_client_tbl) {
+		for (i = 0; i < MAX_DCI_CLIENTS; i++)
+			kfree(driver->dci_client_tbl[i].dci_data);
+	}
+
 	kfree(driver->req_tracking_tbl);
 	kfree(driver->dci_client_tbl);
 	kfree(driver->apps_dci_buf);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 6f37608..684f11d 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -37,6 +37,7 @@
 #define HDLC_OUT_BUF_SIZE	8192
 #define POOL_TYPE_COPY		1
 #define POOL_TYPE_HDLC		2
+#define POOL_TYPE_USER		3
 #define POOL_TYPE_WRITE_STRUCT	4
 #define POOL_TYPE_HSIC		5
 #define POOL_TYPE_HSIC_2	6
@@ -55,7 +56,7 @@
 #define MSG_MASK_SIZE 10000
 #define LOG_MASK_SIZE 8000
 #define EVENT_MASK_SIZE 1000
-#define USER_SPACE_DATA 8000
+#define USER_SPACE_DATA 8192
 #define PKT_SIZE 4096
 #define MAX_EQUIP_ID 15
 #define DIAG_CTRL_MSG_LOG_MASK	9
@@ -234,16 +235,20 @@
 	unsigned int poolsize;
 	unsigned int itemsize_hdlc;
 	unsigned int poolsize_hdlc;
+	unsigned int itemsize_user;
+	unsigned int poolsize_user;
 	unsigned int itemsize_write_struct;
 	unsigned int poolsize_write_struct;
 	unsigned int debug_flag;
 	/* State for the mempool for the char driver */
 	mempool_t *diagpool;
 	mempool_t *diag_hdlc_pool;
+	mempool_t *diag_user_pool;
 	mempool_t *diag_write_struct_pool;
 	struct mutex diagmem_mutex;
 	int count;
 	int count_hdlc_pool;
+	int count_user_pool;
 	int count_write_struct_pool;
 	int used;
 	/* Buffers for masks */
@@ -259,7 +264,6 @@
 	struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
 	unsigned char *usb_buf_out;
 	unsigned char *apps_rsp_buf;
-	unsigned char *user_space_data;
 	/* buffer for updating mask to peripherals */
 	unsigned char *buf_msg_mask_update;
 	unsigned char *buf_log_mask_update;
@@ -276,6 +280,8 @@
 	struct usb_diag_ch *legacy_ch;
 	struct work_struct diag_proc_hdlc_work;
 	struct work_struct diag_read_work;
+	struct work_struct diag_usb_connect_work;
+	struct work_struct diag_usb_disconnect_work;
 #endif
 	struct workqueue_struct *diag_wq;
 	struct work_struct diag_drain_work;
@@ -312,6 +318,7 @@
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 	spinlock_t hsic_ready_spinlock;
 	/* common for all bridges */
+	struct work_struct diag_connect_work;
 	struct work_struct diag_disconnect_work;
 	/* SGLTE variables */
 	int lcid;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index a0c32f5..2ebae71 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -56,13 +56,16 @@
 /* The following variables can be specified by module options */
  /* for copy buffer */
 static unsigned int itemsize = 4096; /*Size of item in the mempool */
-static unsigned int poolsize = 10; /*Number of items in the mempool */
+static unsigned int poolsize = 12; /*Number of items in the mempool */
 /* for hdlc buffer */
 static unsigned int itemsize_hdlc = 8192; /*Size of item in the mempool */
-static unsigned int poolsize_hdlc = 8;  /*Number of items in the mempool */
+static unsigned int poolsize_hdlc = 10;  /*Number of items in the mempool */
+/* for user buffer */
+static unsigned int itemsize_user = 8192; /*Size of item in the mempool */
+static unsigned int poolsize_user = 8;  /*Number of items in the mempool */
 /* for write structure buffer */
 static unsigned int itemsize_write_struct = 20; /*Size of item in the mempool */
-static unsigned int poolsize_write_struct = 8; /* Num of items in the mempool */
+static unsigned int poolsize_write_struct = 10;/* Num of items in the mempool */
 /* This is the max number of user-space clients supported at initialization*/
 static unsigned int max_clients = 15;
 static unsigned int threshold_client_limit = 30;
@@ -781,10 +784,26 @@
 {
 	int i, temp, success = -EINVAL, status;
 	int temp_realtime_mode = driver->real_time_mode;
+	int requested_mode = (int)ioarg;
+
+	switch (requested_mode) {
+	case USB_MODE:
+	case MEMORY_DEVICE_MODE:
+	case NO_LOGGING_MODE:
+	case UART_MODE:
+	case SOCKET_MODE:
+	case CALLBACK_MODE:
+	case MEMORY_DEVICE_MODE_NRT:
+		break;
+	default:
+		pr_err("diag: In %s, request to switch to invalid mode: %d\n",
+			__func__, requested_mode);
+		return -EINVAL;
+	}
 
 	mutex_lock(&driver->diagchar_mutex);
 	temp = driver->logging_mode;
-	driver->logging_mode = (int)ioarg;
+	driver->logging_mode = requested_mode;
 
 	if (driver->logging_mode == MEMORY_DEVICE_MODE_NRT) {
 		diag_send_diag_mode_update(MODE_NONREALTIME);
@@ -1013,6 +1032,8 @@
 					 current->tgid)
 					driver->req_tracking_tbl[i].pid = 0;
 			driver->dci_client_tbl[result].client = NULL;
+			kfree(driver->dci_client_tbl[result].dci_data);
+			driver->dci_client_tbl[result].dci_data = NULL;
 			driver->num_dci_client--;
 		}
 		mutex_unlock(&driver->dci_mutex);
@@ -1362,6 +1383,7 @@
 	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
 	void *buf_copy = NULL;
+	void *user_space_data = NULL;
 	unsigned int payload_size;
 
 	index = 0;
@@ -1388,31 +1410,50 @@
 	}
 #endif /* DIAG over USB */
 	if (pkt_type == DCI_DATA_TYPE) {
-		err = copy_from_user(driver->user_space_data, buf + 4,
-							 payload_size);
+		user_space_data = diagmem_alloc(driver, payload_size,
+								POOL_TYPE_USER);
+		if (!user_space_data) {
+			driver->dropped_count++;
+			return -ENOMEM;
+		}
+		err = copy_from_user(user_space_data, buf + 4, payload_size);
 		if (err) {
 			pr_alert("diag: copy failed for DCI data\n");
 			return DIAG_DCI_SEND_DATA_FAIL;
 		}
-		err = diag_process_dci_transaction(driver->user_space_data,
+		err = diag_process_dci_transaction(user_space_data,
 							payload_size);
+		diagmem_free(driver, user_space_data, POOL_TYPE_USER);
 		return err;
 	}
 	if (pkt_type == CALLBACK_DATA_TYPE) {
-		err = copy_from_user(driver->user_space_data, buf + 4,
-							 payload_size);
-		 if (err) {
+		if (payload_size > itemsize) {
+			pr_err("diag: Dropping packet, packet payload size crosses 4KB limit. Current payload size %d\n",
+				payload_size);
+			driver->dropped_count++;
+			return -EBADMSG;
+		}
+
+		buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
+		if (!buf_copy) {
+			driver->dropped_count++;
+			return -ENOMEM;
+		}
+
+		err = copy_from_user(buf_copy, buf + 4, payload_size);
+		if (err) {
 			pr_err("diag: copy failed for user space data\n");
 			return -EIO;
 		}
 		/* Check for proc_type */
-		remote_proc = diag_get_remote(*(int *)driver->user_space_data);
+		remote_proc = diag_get_remote(*(int *)buf_copy);
 
 		if (!remote_proc) {
 			wait_event_interruptible(driver->wait_q,
 				 (driver->in_busy_pktdata == 0));
-			return diag_process_apps_pkt(driver->user_space_data,
-							payload_size);
+			ret = diag_process_apps_pkt(buf_copy, payload_size);
+			diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+			return ret;
 		}
 		/* The packet is for the remote processor */
 		token_offset = 4;
@@ -1420,8 +1461,8 @@
 		buf += 4;
 		/* Perform HDLC encoding on incoming data */
 		send.state = DIAG_STATE_START;
-		send.pkt = (void *)(driver->user_space_data + token_offset);
-		send.last = (void *)(driver->user_space_data + token_offset -
+		send.pkt = (void *)(buf_copy + token_offset);
+		send.last = (void *)(buf_copy + token_offset -
 							1 + payload_size);
 		send.terminate = 1;
 
@@ -1503,21 +1544,30 @@
 			}
 		}
 #endif
+		diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
 		diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
+		buf_copy = NULL;
 		buf_hdlc = NULL;
 		driver->used = 0;
 		mutex_unlock(&driver->diagchar_mutex);
 		return ret;
 	}
 	if (pkt_type == USER_SPACE_DATA_TYPE) {
-		err = copy_from_user(driver->user_space_data, buf + 4,
+		user_space_data = diagmem_alloc(driver, payload_size,
+								POOL_TYPE_USER);
+		if (!user_space_data) {
+			driver->dropped_count++;
+			return -ENOMEM;
+		}
+		err = copy_from_user(user_space_data, buf + 4,
 							 payload_size);
 		if (err) {
 			pr_err("diag: copy failed for user space data\n");
+			diagmem_free(driver, user_space_data, POOL_TYPE_USER);
 			return -EIO;
 		}
 		/* Check for proc_type */
-		remote_proc = diag_get_remote(*(int *)driver->user_space_data);
+		remote_proc = diag_get_remote(*(int *)user_space_data);
 
 		if (remote_proc) {
 			token_offset = 4;
@@ -1527,9 +1577,11 @@
 
 		/* Check masks for On-Device logging */
 		if (driver->mask_check) {
-			if (!mask_request_validate(driver->user_space_data +
+			if (!mask_request_validate(user_space_data +
 							 token_offset)) {
 				pr_alert("diag: mask request Invalid\n");
+				diagmem_free(driver, user_space_data,
+							POOL_TYPE_USER);
 				return -EFAULT;
 			}
 		}
@@ -1537,7 +1589,7 @@
 #ifdef DIAG_DEBUG
 		pr_debug("diag: user space data %d\n", payload_size);
 		for (i = 0; i < payload_size; i++)
-			pr_debug("\t %x", *((driver->user_space_data
+			pr_debug("\t %x", *((user_space_data
 						+ token_offset)+i));
 #endif
 #ifdef CONFIG_DIAG_SDIO_PIPE
@@ -1548,7 +1600,7 @@
 					 payload_size));
 			if (driver->sdio_ch && (payload_size > 0)) {
 				sdio_write(driver->sdio_ch, (void *)
-				   (driver->user_space_data + token_offset),
+				   (user_space_data + token_offset),
 				   payload_size);
 			}
 		}
@@ -1578,8 +1630,8 @@
 				diag_hsic[index].in_busy_hsic_read_on_device =
 									0;
 				err = diag_bridge_write(index,
-						driver->user_space_data +
-						token_offset, payload_size);
+						user_space_data + token_offset,
+						payload_size);
 				if (err) {
 					pr_err("diag: err sending mask to MDM: %d\n",
 					       err);
@@ -1600,11 +1652,13 @@
 						&& driver->lcid) {
 			if (payload_size > 0) {
 				err = msm_smux_write(driver->lcid, NULL,
-					driver->user_space_data + token_offset,
+					user_space_data + token_offset,
 					payload_size);
 				if (err) {
 					pr_err("diag:send mask to MDM err %d",
 							err);
+					diagmem_free(driver, user_space_data,
+								POOL_TYPE_USER);
 					return err;
 				}
 			}
@@ -1613,8 +1667,8 @@
 		/* send masks to 8k now */
 		if (!remote_proc)
 			diag_process_hdlc((void *)
-				(driver->user_space_data + token_offset),
-				 payload_size);
+				(user_space_data + token_offset), payload_size);
+		diagmem_free(driver, user_space_data, POOL_TYPE_USER);
 		return 0;
 	}
 
@@ -1885,6 +1939,11 @@
 }
 
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+static void diag_connect_work_fn(struct work_struct *w)
+{
+	diagfwd_connect_bridge(1);
+}
+
 static void diag_disconnect_work_fn(struct work_struct *w)
 {
 	diagfwd_disconnect_bridge(1);
@@ -1944,6 +2003,8 @@
 		driver->poolsize = poolsize;
 		driver->itemsize_hdlc = itemsize_hdlc;
 		driver->poolsize_hdlc = poolsize_hdlc;
+		driver->itemsize_user = itemsize_user;
+		driver->poolsize_user = poolsize_user;
 		driver->itemsize_write_struct = itemsize_write_struct;
 		driver->poolsize_write_struct = poolsize_write_struct;
 		driver->num_clients = max_clients;
@@ -1969,6 +2030,8 @@
 			pr_err("diag: could not register HSIC device, ret: %d\n",
 				ret);
 		diagfwd_bridge_init(SMUX);
+		INIT_WORK(&(driver->diag_connect_work),
+						 diag_connect_work_fn);
 		INIT_WORK(&(driver->diag_disconnect_work),
 						 diag_disconnect_work_fn);
 #endif
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a4003ff..151e304 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -402,7 +402,7 @@
 				return;
 			}
 			if (pkt_len > r) {
-				pr_err("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
+				pr_debug("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
 				__func__, pkt_len, r, total_recd, loop_count,
 				smd_info->peripheral, smd_info->type);
 			}
@@ -1282,6 +1282,16 @@
 #define N_LEGACY_WRITE	(driver->poolsize + 6)
 #define N_LEGACY_READ	1
 
+static void diag_usb_connect_work_fn(struct work_struct *w)
+{
+	diagfwd_connect();
+}
+
+static void diag_usb_disconnect_work_fn(struct work_struct *w)
+{
+	diagfwd_disconnect();
+}
+
 int diagfwd_connect(void)
 {
 	int err;
@@ -1448,10 +1458,12 @@
 {
 	switch (event) {
 	case USB_DIAG_CONNECT:
-		diagfwd_connect();
+		queue_work(driver->diag_wq,
+			 &driver->diag_usb_connect_work);
 		break;
 	case USB_DIAG_DISCONNECT:
-		diagfwd_disconnect();
+		queue_work(driver->diag_wq,
+			 &driver->diag_usb_disconnect_work);
 		break;
 	case USB_DIAG_READ_DONE:
 		diagfwd_read_complete(d_req);
@@ -1783,11 +1795,6 @@
 	    && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
 		goto err;
 	kmemleak_not_leak(driver->hdlc_buf);
-	if (driver->user_space_data == NULL)
-		driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
-		if (driver->user_space_data == NULL)
-			goto err;
-	kmemleak_not_leak(driver->user_space_data);
 	if (driver->client_map == NULL &&
 	    (driver->client_map = kzalloc
 	     ((driver->num_clients) * sizeof(struct diag_client_map),
@@ -1832,6 +1839,10 @@
 	}
 	driver->diag_wq = create_singlethread_workqueue("diag_wq");
 #ifdef CONFIG_DIAG_OVER_USB
+	INIT_WORK(&(driver->diag_usb_connect_work),
+						 diag_usb_connect_work_fn);
+	INIT_WORK(&(driver->diag_usb_disconnect_work),
+						 diag_usb_disconnect_work_fn);
 	INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
 	INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
 	driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
@@ -1862,7 +1873,6 @@
 	kfree(driver->pkt_buf);
 	kfree(driver->usb_read_ptr);
 	kfree(driver->apps_rsp_buf);
-	kfree(driver->user_space_data);
 	if (driver->diag_wq)
 		destroy_workqueue(driver->diag_wq);
 }
@@ -1895,6 +1905,5 @@
 	kfree(driver->pkt_buf);
 	kfree(driver->usb_read_ptr);
 	kfree(driver->apps_rsp_buf);
-	kfree(driver->user_space_data);
 	destroy_workqueue(driver->diag_wq);
 }
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index 475f5ba..8c07219b 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -233,7 +233,8 @@
 
 	switch (event) {
 	case USB_DIAG_CONNECT:
-		diagfwd_connect_bridge(1);
+		queue_work(driver->diag_wq,
+			 &driver->diag_connect_work);
 		break;
 	case USB_DIAG_DISCONNECT:
 		queue_work(driver->diag_wq,
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index 0cd8267..bd339e2 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -45,6 +45,15 @@
 								 GFP_ATOMIC);
 			}
 		}
+	} else if (pool_type == POOL_TYPE_USER) {
+		if (driver->diag_user_pool) {
+			if (driver->count_user_pool < driver->poolsize_user) {
+				atomic_add(1,
+					(atomic_t *)&driver->count_user_pool);
+				buf = mempool_alloc(driver->diag_user_pool,
+					GFP_ATOMIC);
+			}
+		}
 	} else if (pool_type == POOL_TYPE_WRITE_STRUCT) {
 		if (driver->diag_write_struct_pool) {
 			if (driver->count_write_struct_pool <
@@ -98,8 +107,9 @@
 			mempool_destroy(driver->diagpool);
 			driver->diagpool = NULL;
 		} else if (driver->ref_count == 0 && pool_type ==
-							POOL_TYPE_ALL)
-			printk(KERN_ALERT "Unable to destroy COPY mempool");
+							POOL_TYPE_ALL) {
+			pr_err("diag: Unable to destroy COPY mempool");
+		}
 	}
 
 	if (driver->diag_hdlc_pool) {
@@ -107,8 +117,19 @@
 			mempool_destroy(driver->diag_hdlc_pool);
 			driver->diag_hdlc_pool = NULL;
 		} else if (driver->ref_count == 0 && pool_type ==
-							POOL_TYPE_ALL)
-			printk(KERN_ALERT "Unable to destroy HDLC mempool");
+							POOL_TYPE_ALL) {
+			pr_err("diag: Unable to destroy HDLC mempool");
+		}
+	}
+
+	if (driver->diag_user_pool) {
+		if (driver->count_user_pool == 0 && driver->ref_count == 0) {
+			mempool_destroy(driver->diag_user_pool);
+			driver->diag_user_pool = NULL;
+		} else if (driver->ref_count == 0 && pool_type ==
+							POOL_TYPE_ALL) {
+			pr_err("diag: Unable to destroy USER mempool");
+		}
 	}
 
 	if (driver->diag_write_struct_pool) {
@@ -119,8 +140,9 @@
 			mempool_destroy(driver->diag_write_struct_pool);
 			driver->diag_write_struct_pool = NULL;
 		} else if (driver->ref_count == 0 && pool_type ==
-								POOL_TYPE_ALL)
-			printk(KERN_ALERT "Unable to destroy STRUCT mempool");
+							POOL_TYPE_ALL) {
+			pr_err("diag: Unable to destroy STRUCT mempool");
+		}
 	}
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 	for (index = 0; index < MAX_HSIC_CH; index++) {
@@ -163,16 +185,25 @@
 			mempool_free(buf, driver->diagpool);
 			atomic_add(-1, (atomic_t *)&driver->count);
 		} else
-			pr_err("diag: Attempt to free up DIAG driver "
-	       "mempool memory which is already free %d", driver->count);
+			pr_err("diag: Attempt to free up DIAG driver mempool memory which is already free %d",
+							driver->count);
 	} else if (pool_type == POOL_TYPE_HDLC) {
 		if (driver->diag_hdlc_pool != NULL &&
 			 driver->count_hdlc_pool > 0) {
 			mempool_free(buf, driver->diag_hdlc_pool);
 			atomic_add(-1, (atomic_t *)&driver->count_hdlc_pool);
 		} else
-			pr_err("diag: Attempt to free up DIAG driver "
-	"HDLC mempool which is already free %d ", driver->count_hdlc_pool);
+			pr_err("diag: Attempt to free up DIAG driver HDLC mempool which is already free %d ",
+						driver->count_hdlc_pool);
+	} else if (pool_type == POOL_TYPE_USER) {
+		if (driver->diag_user_pool != NULL &&
+			driver->count_user_pool > 0) {
+			mempool_free(buf, driver->diag_user_pool);
+			atomic_add(-1, (atomic_t *)&driver->count_user_pool);
+		} else {
+			pr_err("diag: Attempt to free up DIAG driver USER mempool which is already free %d ",
+						driver->count_user_pool);
+		}
 	} else if (pool_type == POOL_TYPE_WRITE_STRUCT) {
 		if (driver->diag_write_struct_pool != NULL &&
 			 driver->count_write_struct_pool > 0) {
@@ -180,9 +211,8 @@
 			atomic_add(-1,
 				 (atomic_t *)&driver->count_write_struct_pool);
 		} else
-			pr_err("diag: Attempt to free up DIAG driver "
-			   "USB structure mempool which is already free %d ",
-				    driver->count_write_struct_pool);
+			pr_err("diag: Attempt to free up DIAG driver USB structure mempool which is already free %d ",
+					driver->count_write_struct_pool);
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 	} else if (pool_type == POOL_TYPE_HSIC ||
 				pool_type == POOL_TYPE_HSIC_2) {
@@ -229,18 +259,25 @@
 		driver->diag_hdlc_pool = mempool_create_kmalloc_pool(
 				driver->poolsize_hdlc, driver->itemsize_hdlc);
 
+	if (driver->count_user_pool == 0)
+		driver->diag_user_pool = mempool_create_kmalloc_pool(
+				driver->poolsize_user, driver->itemsize_user);
+
 	if (driver->count_write_struct_pool == 0)
 		driver->diag_write_struct_pool = mempool_create_kmalloc_pool(
 		driver->poolsize_write_struct, driver->itemsize_write_struct);
 
 	if (!driver->diagpool)
-		printk(KERN_INFO "Cannot allocate diag mempool\n");
+		pr_err("diag: Cannot allocate diag mempool\n");
 
 	if (!driver->diag_hdlc_pool)
-		printk(KERN_INFO "Cannot allocate diag HDLC mempool\n");
+		pr_err("diag: Cannot allocate diag HDLC mempool\n");
+
+	if (!driver->diag_user_pool)
+		pr_err("diag: Cannot allocate diag USER mempool\n");
 
 	if (!driver->diag_write_struct_pool)
-		printk(KERN_INFO "Cannot allocate diag USB struct mempool\n");
+		pr_err("diag: Cannot allocate diag USB struct mempool\n");
 }
 
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index f0b9b05..89500f9 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -127,6 +127,7 @@
 			u32 cont_err_counter;
 			u32 ts_packets_num;
 			u32 ts_dropped_bytes;
+			u64 stc;
 		} buf;
 
 		struct {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index ca71c06..5e7a09e 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -2406,6 +2406,7 @@
 		event.params.es_data.pts = dmx_data_ready->buf.pts;
 		event.params.es_data.dts_valid = dmx_data_ready->buf.dts_exists;
 		event.params.es_data.dts = dmx_data_ready->buf.dts;
+		event.params.es_data.stc = dmx_data_ready->buf.stc;
 		event.params.es_data.transport_error_indicator_counter =
 				dmx_data_ready->buf.tei_counter;
 		event.params.es_data.continuity_error_counter =
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 263241b..04afec0 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -660,22 +660,35 @@
 	}
 }
 
-static int msm_isp_attach_ctx(struct msm_isp_buf_mgr *buf_mgr,
-	struct device *iommu_ctx)
+static void msm_isp_register_ctx(struct msm_isp_buf_mgr *buf_mgr,
+	struct device **iommu_ctx, int num_iommu_ctx)
 {
-	int rc;
-	rc = iommu_attach_device(buf_mgr->iommu_domain, iommu_ctx);
-	if (rc) {
-		pr_err("%s: Iommu attach error\n", __func__);
-		return -EINVAL;
+	int i;
+	buf_mgr->num_iommu_ctx = num_iommu_ctx;
+	for (i = 0; i < num_iommu_ctx; i++)
+		buf_mgr->iommu_ctx[i] = iommu_ctx[i];
+}
+
+static int msm_isp_attach_ctx(struct msm_isp_buf_mgr *buf_mgr)
+{
+	int rc, i;
+	for (i = 0; i < buf_mgr->num_iommu_ctx; i++) {
+		rc = iommu_attach_device(buf_mgr->iommu_domain,
+			buf_mgr->iommu_ctx[i]);
+		if (rc) {
+			pr_err("%s: Iommu attach error\n", __func__);
+			return -EINVAL;
+		}
 	}
 	return 0;
 }
 
-static void msm_isp_detach_ctx(struct msm_isp_buf_mgr *buf_mgr,
-	struct device *iommu_ctx)
+static void msm_isp_detach_ctx(struct msm_isp_buf_mgr *buf_mgr)
 {
-	iommu_detach_device(buf_mgr->iommu_domain, iommu_ctx);
+	int i;
+	for (i = 0; i < buf_mgr->num_iommu_ctx; i++)
+		iommu_detach_device(buf_mgr->iommu_domain,
+			buf_mgr->iommu_ctx[i]);
 }
 
 static int msm_isp_init_isp_buf_mgr(
@@ -692,6 +705,7 @@
 	}
 
 	CDBG("%s: E\n", __func__);
+	msm_isp_attach_ctx(buf_mgr);
 	buf_mgr->num_buf_q = num_buf_q;
 	buf_mgr->bufq =
 		kzalloc(sizeof(struct msm_isp_bufq) * num_buf_q,
@@ -716,6 +730,7 @@
 	ion_client_destroy(buf_mgr->client);
 	kfree(buf_mgr->bufq);
 	buf_mgr->num_buf_q = 0;
+	msm_isp_detach_ctx(buf_mgr);
 	return 0;
 }
 
@@ -752,8 +767,7 @@
 	.flush_buf = msm_isp_flush_buf,
 	.buf_done = msm_isp_buf_done,
 	.buf_divert = msm_isp_buf_divert,
-	.attach_ctx = msm_isp_attach_ctx,
-	.detach_ctx = msm_isp_detach_ctx,
+	.register_ctx = msm_isp_register_ctx,
 	.buf_mgr_init = msm_isp_init_isp_buf_mgr,
 	.buf_mgr_deinit = msm_isp_deinit_isp_buf_mgr,
 };
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
index 066d02a..fda1a57 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
@@ -112,10 +112,8 @@
 	int (*buf_divert) (struct msm_isp_buf_mgr *buf_mgr,
 		uint32_t bufq_handle, uint32_t buf_index,
 		struct timeval *tv, uint32_t frame_id);
-	int (*attach_ctx) (struct msm_isp_buf_mgr *buf_mgr,
-		struct device *iommu_ctx);
-	void (*detach_ctx) (struct msm_isp_buf_mgr *buf_mgr,
-		struct device *iommu_ctx);
+	void (*register_ctx) (struct msm_isp_buf_mgr *buf_mgr,
+		struct device **iommu_ctx, int num_iommu_ctx);
 	int (*buf_mgr_init) (struct msm_isp_buf_mgr *buf_mgr,
 		const char *ctx_name, uint16_t num_buf_q);
 	int (*buf_mgr_deinit) (struct msm_isp_buf_mgr *buf_mgr);
@@ -137,6 +135,9 @@
 	/*IOMMU specific*/
 	int iommu_domain_num;
 	struct iommu_domain *iommu_domain;
+
+	int num_iommu_ctx;
+	struct device *iommu_ctx[2];
 };
 
 int msm_isp_create_isp_buf_mgr(struct msm_isp_buf_mgr *buf_mgr,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index 447c752..b31b3f1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -138,6 +138,8 @@
 		kfree(vfe_dev);
 		return -EINVAL;
 	}
+	vfe_dev->buf_mgr->ops->register_ctx(vfe_dev->buf_mgr,
+		&vfe_dev->iommu_ctx[0], vfe_dev->hw_info->num_iommu_ctx);
 	vfe_dev->vfe_open_cnt = 0;
 end:
 	return rc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 1b762ea..7bc2b7d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -148,7 +148,8 @@
 		struct msm_vfe_stats_stream *stream_info);
 	void (*clear_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_stats_stream *stream_info);
-	void (*cfg_comp_mask) (struct vfe_device *vfe_dev);
+	void (*cfg_comp_mask) (struct vfe_device *vfe_dev,
+		uint32_t stats_mask, uint8_t enable);
 	void (*cfg_wm_irq_mask) (struct vfe_device *vfe_dev,
 		struct msm_vfe_stats_stream *stream_info);
 	void (*clear_wm_irq_mask) (struct vfe_device *vfe_dev,
@@ -294,6 +295,7 @@
 		composite_info[MAX_NUM_COMPOSITE_MASK];
 	uint8_t num_used_composite_mask;
 	uint32_t stream_update;
+	enum msm_isp_camif_update_state pipeline_update;
 	struct msm_vfe_src_info src_info[VFE_SRC_MAX];
 	uint16_t stream_handle_cnt;
 	unsigned long event_mask;
@@ -312,6 +314,7 @@
 	STATS_ACTIVE,
 	STATS_START_PENDING,
 	STATS_STOP_PENDING,
+	STATS_STARTING,
 	STATS_STOPPING,
 };
 
@@ -319,9 +322,11 @@
 	uint32_t session_id;
 	uint32_t stream_id;
 	uint32_t stream_handle;
+	uint32_t composite_flag;
 	enum msm_isp_stats_type stats_type;
 	enum msm_vfe_stats_state state;
 	uint32_t framedrop_pattern;
+	uint32_t framedrop_period;
 	uint32_t irq_subsample_pattern;
 
 	uint32_t buffer_offset;
@@ -331,11 +336,10 @@
 
 struct msm_vfe_stats_shared_data {
 	struct msm_vfe_stats_stream stream_info[MSM_ISP_STATS_MAX];
-	enum msm_vfe_stats_pipeline_policy stats_pipeline_policy;
-	uint32_t comp_framedrop_pattern;
-	uint32_t comp_irq_subsample_pattern;
 	uint8_t num_active_stream;
+	atomic_t stats_comp_mask;
 	uint16_t stream_handle_cnt;
+	atomic_t stats_update;
 };
 
 struct msm_vfe_tasklet_queue_cmd {
@@ -380,6 +384,7 @@
 	struct completion reset_complete;
 	struct completion halt_complete;
 	struct completion stream_config_complete;
+	struct completion stats_config_complete;
 	struct mutex realtime_mutex;
 	struct mutex core_mutex;
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index d4f6a07..a251f0a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -114,7 +114,7 @@
 	msm_camera_io_w(0x07FFFFFF, vfe_dev->vfe_base + 0xC);
 	/* BUS_CFG */
 	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x3C);
-	msm_camera_io_w(0x00000025, vfe_dev->vfe_base + 0x1C);
+	msm_camera_io_w(0x01000025, vfe_dev->vfe_base + 0x1C);
 	msm_camera_io_w_mb(0x1DFFFFFF, vfe_dev->vfe_base + 0x20);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
 	msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
@@ -304,6 +304,8 @@
 
 	if (vfe_dev->axi_data.stream_update)
 		msm_isp_axi_stream_update(vfe_dev);
+	if (atomic_read(&vfe_dev->stats_data.stats_update))
+		msm_isp_stats_stream_update(vfe_dev);
 	msm_isp_update_framedrop_reg(vfe_dev);
 	msm_isp_update_error_frame_count(vfe_dev);
 
@@ -767,7 +769,8 @@
 	}
 }
 
-static void msm_vfe32_stats_cfg_comp_mask(struct vfe_device *vfe_dev)
+static void msm_vfe32_stats_cfg_comp_mask(struct vfe_device *vfe_dev,
+	uint32_t stats_mask, uint8_t enable)
 {
 	return;
 }
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 256d136..5a17635 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -266,7 +266,7 @@
 	msm_camera_io_w(0xC001FF7F, vfe_dev->vfe_base + 0x974);
 	/* BUS_CFG */
 	msm_camera_io_w(0x10000001, vfe_dev->vfe_base + 0x50);
-	msm_camera_io_w(0x800000F3, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w(0xE00000F3, vfe_dev->vfe_base + 0x28);
 	msm_camera_io_w_mb(0xFEFFFFFF, vfe_dev->vfe_base + 0x2C);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30);
 	msm_camera_io_w_mb(0xFEFFFFFF, vfe_dev->vfe_base + 0x34);
@@ -466,6 +466,8 @@
 
 	if (vfe_dev->axi_data.stream_update)
 		msm_isp_axi_stream_update(vfe_dev);
+	if (atomic_read(&vfe_dev->stats_data.stats_update))
+		msm_isp_stats_stream_update(vfe_dev);
 	msm_isp_update_framedrop_reg(vfe_dev);
 	msm_isp_update_error_frame_count(vfe_dev);
 
@@ -1003,12 +1005,16 @@
 	}
 }
 
-static void msm_vfe40_stats_cfg_comp_mask(struct vfe_device *vfe_dev)
+static void msm_vfe40_stats_cfg_comp_mask(struct vfe_device *vfe_dev,
+	uint32_t stats_mask, uint8_t enable)
 {
-	if (vfe_dev->stats_data.stats_pipeline_policy == STATS_COMP_ALL)
-		msm_camera_io_w(0x00FF0000, vfe_dev->vfe_base + 0x44);
+	uint32_t comp_mask;
+	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x44) >> 16;
+	if (enable)
+		comp_mask |= stats_mask;
 	else
-		msm_camera_io_w(0x00000000, vfe_dev->vfe_base + 0x44);
+		comp_mask &= ~stats_mask;
+	msm_camera_io_w(comp_mask << 16, vfe_dev->vfe_base + 0x44);
 }
 
 static void msm_vfe40_stats_cfg_wm_irq_mask(
@@ -1039,9 +1045,10 @@
 	uint32_t stats_base = VFE40_STATS_BASE(stats_idx);
 
 	/*WR_ADDR_CFG*/
-	msm_camera_io_w(0x7C, vfe_dev->vfe_base + stats_base + 0x8);
+	msm_camera_io_w(stream_info->framedrop_period << 2,
+		vfe_dev->vfe_base + stats_base + 0x8);
 	/*WR_IRQ_FRAMEDROP_PATTERN*/
-	msm_camera_io_w(0xFFFFFFFF,
+	msm_camera_io_w(stream_info->framedrop_pattern,
 		vfe_dev->vfe_base + stats_base + 0x10);
 	/*WR_IRQ_SUBSAMPLE_PATTERN*/
 	msm_camera_io_w(0xFFFFFFFF,
@@ -1189,11 +1196,9 @@
 		goto vfe_no_resource;
 	}
 
-	if (vfe_dev->pdev->id == 0)
-		vfe_dev->iommu_ctx[0] = msm_iommu_get_ctx("vfe0");
-	else if (vfe_dev->pdev->id == 1)
-		vfe_dev->iommu_ctx[0] = msm_iommu_get_ctx("vfe1");
-	if (!vfe_dev->iommu_ctx[0]) {
+	vfe_dev->iommu_ctx[0] = msm_iommu_get_ctx("vfe0");
+	vfe_dev->iommu_ctx[1] = msm_iommu_get_ctx("vfe1");
+	if (!vfe_dev->iommu_ctx[0] || !vfe_dev->iommu_ctx[1]) {
 		pr_err("%s: cannot get iommu_ctx\n", __func__);
 		rc = -ENODEV;
 		goto vfe_no_resource;
@@ -1245,7 +1250,7 @@
 };
 
 struct msm_vfe_hardware_info vfe40_hw_info = {
-	.num_iommu_ctx = 1,
+	.num_iommu_ctx = 2,
 	.vfe_clk_idx = VFE40_CLK_IDX,
 	.vfe_ops = {
 		.irq_ops = {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 477985d..728e172 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -389,31 +389,6 @@
 	msm_isp_send_event(vfe_dev, ISP_EVENT_SOF, &sof_event);
 }
 
-uint32_t msm_isp_get_framedrop_period(
-	enum msm_vfe_frame_skip_pattern frame_skip_pattern)
-{
-	switch (frame_skip_pattern) {
-	case NO_SKIP:
-	case EVERY_2FRAME:
-	case EVERY_3FRAME:
-	case EVERY_4FRAME:
-	case EVERY_5FRAME:
-	case EVERY_6FRAME:
-	case EVERY_7FRAME:
-	case EVERY_8FRAME:
-		return frame_skip_pattern + 1;
-	case EVERY_16FRAME:
-		return 16;
-		break;
-	case EVERY_32FRAME:
-		return 32;
-		break;
-	default:
-		return 1;
-	}
-	return 1;
-}
-
 void msm_isp_calculate_framedrop(
 	struct msm_vfe_axi_shared_data *axi_data,
 	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
@@ -611,6 +586,13 @@
 				ACTIVE : INACTIVE;
 		}
 	}
+
+	if (vfe_dev->axi_data.pipeline_update == DISABLE_CAMIF) {
+		vfe_dev->hw_info->vfe_ops.stats_ops.
+			enable_module(vfe_dev, 0xFF, 0);
+		vfe_dev->axi_data.pipeline_update = NO_UPDATE;
+	}
+
 	vfe_dev->axi_data.stream_update--;
 	if (vfe_dev->axi_data.stream_update == 0)
 		complete(&vfe_dev->stream_config_complete);
@@ -849,12 +831,14 @@
 	return rc;
 }
 
-static int msm_isp_axi_wait_for_cfg_done(struct vfe_device *vfe_dev)
+static int msm_isp_axi_wait_for_cfg_done(struct vfe_device *vfe_dev,
+	enum msm_isp_camif_update_state camif_update)
 {
 	int rc;
 	unsigned long flags;
 	spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
 	init_completion(&vfe_dev->stream_config_complete);
+	vfe_dev->axi_data.pipeline_update = camif_update;
 	vfe_dev->axi_data.stream_update = 2;
 	spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
 	rc = wait_for_completion_interruptible_timeout(
@@ -958,7 +942,7 @@
 			update_camif_state(vfe_dev, camif_update);
 
 	if (wait_for_complete)
-		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
 
 	return rc;
 }
@@ -976,7 +960,7 @@
 		stream_info->state = STOP_PENDING;
 	}
 
-	rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+	rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
 	if (rc < 0) {
 		pr_err("%s: wait for config done failed\n", __func__);
 		return rc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index c47209f..e08dea2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/io.h>
+#include <linux/atomic.h>
 #include <media/v4l2-subdev.h>
 #include "msm_isp_util.h"
 #include "msm_isp_stats_util.h"
@@ -67,6 +68,7 @@
 	struct msm_isp_buffer *done_buf;
 	struct msm_vfe_stats_stream *stream_info = NULL;
 	uint32_t pingpong_status;
+	uint32_t comp_stats_type_mask = 0;
 	uint32_t stats_comp_mask = 0, stats_irq_mask = 0;
 	stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
 		get_comp_mask(irq_status0, irq_status1);
@@ -76,13 +78,17 @@
 		return;
 	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
 
-	if (vfe_dev->stats_data.stats_pipeline_policy == STATS_COMP_ALL) {
-		if (!stats_comp_mask)
-			return;
-		stats_irq_mask = 0xFFFFFFFF;
-	}
+	if (!stats_comp_mask)
+		stats_irq_mask &=
+			~atomic_read(&vfe_dev->stats_data.stats_comp_mask);
+	else
+		stats_irq_mask |=
+			atomic_read(&vfe_dev->stats_data.stats_comp_mask);
 
 	memset(&buf_event, 0, sizeof(struct msm_isp_event_data));
+	buf_event.timestamp = ts->event_time;
+	buf_event.frame_id =
+		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
 	pingpong_status = vfe_dev->hw_info->
 		vfe_ops.stats_ops.get_pingpong_status(vfe_dev);
 
@@ -98,22 +104,32 @@
 				done_buf->bufq_handle, done_buf->buf_idx,
 				&ts->buf_time, vfe_dev->axi_data.
 				src_info[VFE_PIX_0].frame_id);
-			if (rc == 0) {
-				stats_event->stats_mask |=
+			if (rc != 0)
+				continue;
+
+			stats_event->stats_buf_idxs[stream_info->stats_type] =
+				done_buf->buf_idx;
+			if (!stream_info->composite_flag) {
+				stats_event->stats_mask =
 					1 << stream_info->stats_type;
-				stats_event->stats_buf_idxs[
-					stream_info->stats_type] =
-					done_buf->buf_idx;
+				ISP_DBG("%s: stats event frame id: 0x%x\n",
+					__func__, buf_event.frame_id);
+				msm_isp_send_event(vfe_dev,
+					ISP_EVENT_STATS_NOTIFY +
+					stream_info->stats_type, &buf_event);
+			} else {
+				comp_stats_type_mask |=
+					1 << stream_info->stats_type;
 			}
 		}
 	}
 
-	if (stats_event->stats_mask) {
-		buf_event.timestamp = ts->event_time;
-		buf_event.frame_id =
-			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
-		msm_isp_send_event(vfe_dev, ISP_EVENT_STATS_NOTIFY +
-				stream_info->stats_type, &buf_event);
+	if (comp_stats_type_mask) {
+		ISP_DBG("%s: composite stats event frame id: 0x%x mask: 0x%x\n",
+			__func__, buf_event.frame_id, comp_stats_type_mask);
+		stats_event->stats_mask = comp_stats_type_mask;
+		msm_isp_send_event(vfe_dev,
+			ISP_EVENT_COMP_STATS_NOTIFY, &buf_event);
 	}
 }
 
@@ -140,36 +156,19 @@
 		return rc;
 	}
 
-	if (stats_data->stats_pipeline_policy != STATS_COMP_ALL) {
-		if (stream_req_cmd->framedrop_pattern >= MAX_SKIP) {
-			pr_err("%s: Invalid framedrop pattern\n", __func__);
-			return rc;
-		}
+	if (stream_req_cmd->framedrop_pattern >= MAX_SKIP) {
+		pr_err("%s: Invalid framedrop pattern\n", __func__);
+		return rc;
+	}
 
-		if (stream_req_cmd->irq_subsample_pattern >= MAX_SKIP) {
-			pr_err("%s: Invalid irq subsample pattern\n", __func__);
-			return rc;
-		}
-	} else {
-		if (stats_data->comp_framedrop_pattern >= MAX_SKIP) {
-			pr_err("%s: Invalid comp framedrop pattern\n",
-				__func__);
-			return rc;
-		}
-
-		if (stats_data->comp_irq_subsample_pattern >= MAX_SKIP) {
-			pr_err("%s: Invalid comp irq subsample pattern\n",
-				__func__);
-			return rc;
-		}
-		stream_req_cmd->framedrop_pattern =
-			vfe_dev->stats_data.comp_framedrop_pattern;
-		stream_req_cmd->irq_subsample_pattern =
-			vfe_dev->stats_data.comp_irq_subsample_pattern;
+	if (stream_req_cmd->irq_subsample_pattern >= MAX_SKIP) {
+		pr_err("%s: Invalid irq subsample pattern\n", __func__);
+		return rc;
 	}
 
 	stream_info->session_id = stream_req_cmd->session_id;
 	stream_info->stream_id = stream_req_cmd->stream_id;
+	stream_info->composite_flag = stream_req_cmd->composite_flag;
 	stream_info->stats_type = stream_req_cmd->stats_type;
 	stream_info->buffer_offset = stream_req_cmd->buffer_offset;
 	stream_info->framedrop_pattern = stream_req_cmd->framedrop_pattern;
@@ -193,6 +192,7 @@
 	struct msm_vfe_stats_stream_request_cmd *stream_req_cmd = arg;
 	struct msm_vfe_stats_stream *stream_info = NULL;
 	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	uint32_t framedrop_period;
 	uint32_t stats_idx;
 
 	rc = msm_isp_stats_create_stream(vfe_dev, stream_req_cmd);
@@ -204,31 +204,12 @@
 	stats_idx = STATS_IDX(stream_req_cmd->stream_handle);
 	stream_info = &stats_data->stream_info[stats_idx];
 
-	switch (stream_info->framedrop_pattern) {
-	case NO_SKIP:
-		stream_info->framedrop_pattern = VFE_NO_DROP;
-		break;
-	case EVERY_2FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_2FRAME;
-		break;
-	case EVERY_4FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_4FRAME;
-		break;
-	case EVERY_8FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_8FRAME;
-		break;
-	case EVERY_16FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_16FRAME;
-		break;
-	case EVERY_32FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_32FRAME;
-		break;
-	default:
-		stream_info->framedrop_pattern = VFE_NO_DROP;
-		break;
-	}
+	framedrop_period = msm_isp_get_framedrop_period(
+	   stream_req_cmd->framedrop_pattern);
+	stream_info->framedrop_pattern = 0x1;
+	stream_info->framedrop_period = framedrop_period - 1;
 
-	if (stats_data->stats_pipeline_policy == STATS_COMP_NONE)
+	if (!stream_info->composite_flag)
 		vfe_dev->hw_info->vfe_ops.stats_ops.
 			cfg_wm_irq_mask(vfe_dev, stream_info);
 
@@ -257,7 +238,7 @@
 		rc = msm_isp_cfg_stats_stream(vfe_dev, &stream_cfg_cmd);
 	}
 
-	if (stats_data->stats_pipeline_policy == STATS_COMP_NONE)
+	if (!stream_info->composite_flag)
 		vfe_dev->hw_info->vfe_ops.stats_ops.
 			clear_wm_irq_mask(vfe_dev, stream_info);
 
@@ -266,18 +247,145 @@
 	return 0;
 }
 
-int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg)
+static int msm_isp_init_stats_ping_pong_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+	int rc = 0;
+	stream_info->bufq_handle =
+		vfe_dev->buf_mgr->ops->get_bufq_handle(
+		vfe_dev->buf_mgr, stream_info->session_id,
+		stream_info->stream_id);
+	if (stream_info->bufq_handle == 0) {
+		pr_err("%s: no buf configured for stream: 0x%x\n",
+			__func__, stream_info->stream_handle);
+		return -EINVAL;
+	}
+
+	rc = msm_isp_stats_cfg_ping_pong_address(vfe_dev,
+		stream_info, VFE_PING_FLAG, NULL);
+	if (rc < 0) {
+		pr_err("%s: No free buffer for ping\n", __func__);
+		return rc;
+	}
+	rc = msm_isp_stats_cfg_ping_pong_address(vfe_dev,
+		stream_info, VFE_PONG_FLAG, NULL);
+	if (rc < 0) {
+		pr_err("%s: No free buffer for pong\n", __func__);
+		return rc;
+	}
+	return rc;
+}
+
+void msm_isp_stats_stream_update(struct vfe_device *vfe_dev)
+{
+	int i;
+	uint32_t stats_mask = 0, comp_stats_mask = 0;
+	uint32_t enable = 0;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	for (i = 0; i < vfe_dev->hw_info->stats_hw_info->num_stats_type; i++) {
+		if (stats_data->stream_info[i].state == STATS_START_PENDING ||
+				stats_data->stream_info[i].state ==
+					STATS_STOP_PENDING) {
+			stats_mask |= i;
+			enable = stats_data->stream_info[i].state ==
+				STATS_START_PENDING ? 1 : 0;
+			stats_data->stream_info[i].state =
+				stats_data->stream_info[i].state ==
+				STATS_START_PENDING ?
+				STATS_STARTING : STATS_STOPPING;
+			vfe_dev->hw_info->vfe_ops.stats_ops.enable_module(
+				vfe_dev, BIT(i), enable);
+			vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(
+			   vfe_dev, BIT(i), enable);
+		} else if (stats_data->stream_info[i].state == STATS_STARTING ||
+			stats_data->stream_info[i].state == STATS_STOPPING) {
+			if (stats_data->stream_info[i].composite_flag)
+				comp_stats_mask |= i;
+			if (stats_data->stream_info[i].state == STATS_STARTING)
+				atomic_add(BIT(i),
+					&stats_data->stats_comp_mask);
+			else
+				atomic_sub(BIT(i),
+					&stats_data->stats_comp_mask);
+			stats_data->stream_info[i].state =
+				stats_data->stream_info[i].state ==
+				STATS_STARTING ? STATS_ACTIVE : STATS_INACTIVE;
+		}
+	}
+	atomic_sub(1, &stats_data->stats_update);
+	if (!atomic_read(&stats_data->stats_update))
+		complete(&vfe_dev->stats_config_complete);
+}
+
+static int msm_isp_stats_wait_for_cfg_done(struct vfe_device *vfe_dev)
+{
+	int rc;
+	init_completion(&vfe_dev->stats_config_complete);
+	atomic_set(&vfe_dev->stats_data.stats_update, 2);
+	rc = wait_for_completion_interruptible_timeout(
+		&vfe_dev->stats_config_complete,
+		msecs_to_jiffies(500));
+	if (rc == 0) {
+		pr_err("%s: wait timeout\n", __func__);
+		rc = -1;
+	} else {
+		rc = 0;
+	}
+	return rc;
+}
+
+static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd)
 {
 	int i, rc = 0;
-	struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd = arg;
+	uint32_t stats_mask = 0, comp_stats_mask = 0, idx;
 	struct msm_vfe_stats_stream *stream_info;
 	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
-	int idx;
-	uint32_t stats_mask = 0;
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
+		stream_info = &stats_data->stream_info[idx];
+		if (stream_info->stream_handle !=
+				stream_cfg_cmd->stream_handle[i]) {
+			pr_err("%s: Invalid stream handle: 0x%x received\n",
+				__func__, stream_cfg_cmd->stream_handle[i]);
+			continue;
+		}
+		rc = msm_isp_init_stats_ping_pong_reg(vfe_dev, stream_info);
+		if (rc < 0) {
+			pr_err("%s: No buffer for stream%d\n", __func__, idx);
+			return rc;
+		}
 
-	if (stats_data->num_active_stream == 0)
-		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_ub(vfe_dev);
+		if (vfe_dev->axi_data.src_info[VFE_PIX_0].active)
+			stream_info->state = STATS_START_PENDING;
+		else
+			stream_info->state = STATS_ACTIVE;
 
+		stats_data->num_active_stream++;
+		stats_mask |= 1 << idx;
+		if (stream_info->composite_flag)
+			comp_stats_mask |= 1 << idx;
+	}
+	if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) {
+		rc = msm_isp_stats_wait_for_cfg_done(vfe_dev);
+	} else {
+		vfe_dev->hw_info->vfe_ops.stats_ops.enable_module(
+			vfe_dev, stats_mask, stream_cfg_cmd->enable);
+		atomic_add(comp_stats_mask, &stats_data->stats_comp_mask);
+		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(
+		   vfe_dev, comp_stats_mask, 1);
+	}
+	return rc;
+}
+
+static int msm_isp_stop_stats_stream(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd)
+{
+	int i, rc = 0;
+	uint32_t stats_mask = 0, comp_stats_mask = 0, idx;
+	struct msm_vfe_stats_stream *stream_info;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
 		stream_info = &stats_data->stream_info[idx];
@@ -288,71 +396,39 @@
 			continue;
 		}
 
-		if (stream_cfg_cmd->enable) {
-			stream_info->bufq_handle =
-				vfe_dev->buf_mgr->ops->get_bufq_handle(
-				vfe_dev->buf_mgr, stream_info->session_id,
-				stream_info->stream_id);
-				if (stream_info->bufq_handle == 0) {
-					pr_err("%s: no buf configured for stream: 0x%x\n",
-						__func__,
-						stream_info->stream_handle);
-					return -EINVAL;
-				}
-
-			msm_isp_stats_cfg_ping_pong_address(vfe_dev,
-				stream_info, VFE_PING_FLAG, NULL);
-			msm_isp_stats_cfg_ping_pong_address(vfe_dev,
-				stream_info, VFE_PONG_FLAG, NULL);
-			stream_info->state = STATS_START_PENDING;
-			stats_data->num_active_stream++;
-		} else {
+		if (vfe_dev->axi_data.src_info[VFE_PIX_0].active)
 			stream_info->state = STATS_STOP_PENDING;
-			stats_data->num_active_stream--;
-		}
+		else
+			stream_info->state = STATS_INACTIVE;
+
+		stats_data->num_active_stream--;
 		stats_mask |= 1 << idx;
+		if (stream_info->composite_flag)
+			comp_stats_mask |= 1 << idx;
 	}
-	vfe_dev->hw_info->vfe_ops.stats_ops.
-		enable_module(vfe_dev, stats_mask, stream_cfg_cmd->enable);
+	if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) {
+		rc = msm_isp_stats_wait_for_cfg_done(vfe_dev);
+	} else {
+		vfe_dev->hw_info->vfe_ops.stats_ops.enable_module(
+			vfe_dev, stats_mask, stream_cfg_cmd->enable);
+		atomic_sub(comp_stats_mask, &stats_data->stats_comp_mask);
+		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(
+		   vfe_dev, comp_stats_mask, 0);
+	}
 	return rc;
 }
 
-int msm_isp_cfg_stats_comp_policy(struct vfe_device *vfe_dev, void *arg)
+int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg)
 {
-	int rc = -1;
-	struct msm_vfe_stats_comp_policy_cfg *policy_cfg_cmd = arg;
-	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	int rc = 0;
+	struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd = arg;
+	if (vfe_dev->stats_data.num_active_stream == 0)
+		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_ub(vfe_dev);
 
-	if (stats_data->num_active_stream != 0) {
-		pr_err("%s: Cannot update policy when there are active streams\n",
-			   __func__);
-		return rc;
-	}
+	if (stream_cfg_cmd->enable)
+		rc = msm_isp_start_stats_stream(vfe_dev, stream_cfg_cmd);
+	else
+		rc = msm_isp_stop_stats_stream(vfe_dev, stream_cfg_cmd);
 
-	if (policy_cfg_cmd->stats_pipeline_policy >= MAX_STATS_POLICY) {
-		pr_err("%s: Invalid stats composite policy\n", __func__);
-		return rc;
-	}
-
-	if (policy_cfg_cmd->comp_framedrop_pattern >= MAX_SKIP) {
-		pr_err("%s: Invalid comp framedrop pattern\n", __func__);
-		return rc;
-	}
-
-	if (policy_cfg_cmd->comp_irq_subsample_pattern >= MAX_SKIP) {
-		pr_err("%s: Invalid comp irq subsample pattern\n", __func__);
-		return rc;
-	}
-
-	stats_data->stats_pipeline_policy =
-		policy_cfg_cmd->stats_pipeline_policy;
-	stats_data->comp_framedrop_pattern =
-		policy_cfg_cmd->comp_framedrop_pattern;
-	stats_data->comp_irq_subsample_pattern =
-		policy_cfg_cmd->comp_irq_subsample_pattern;
-
-	vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(vfe_dev);
-
-	return 0;
+	return rc;
 }
-
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h
index 13e1fd6..7b4c4b4 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h
@@ -18,8 +18,8 @@
 void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1,
 	struct msm_isp_timestamp *ts);
+void msm_isp_stats_stream_update(struct vfe_device *vfe_dev);
 int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg);
-int msm_isp_cfg_stats_comp_policy(struct vfe_device *vfe_dev, void *arg);
 #endif /* __MSM_ISP_STATS_UTIL_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 2b047ad..e20a0eb 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -154,6 +154,31 @@
 	mutex_unlock(&bandwidth_mgr_mutex);
 }
 
+uint32_t msm_isp_get_framedrop_period(
+	enum msm_vfe_frame_skip_pattern frame_skip_pattern)
+{
+	switch (frame_skip_pattern) {
+	case NO_SKIP:
+	case EVERY_2FRAME:
+	case EVERY_3FRAME:
+	case EVERY_4FRAME:
+	case EVERY_5FRAME:
+	case EVERY_6FRAME:
+	case EVERY_7FRAME:
+	case EVERY_8FRAME:
+		return frame_skip_pattern + 1;
+	case EVERY_16FRAME:
+		return 16;
+		break;
+	case EVERY_32FRAME:
+		return 32;
+		break;
+	default:
+		return 1;
+	}
+	return 1;
+}
+
 static inline void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp)
 {
 	struct timespec ts;
@@ -355,11 +380,6 @@
 		rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
-	case VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY:
-		mutex_lock(&vfe_dev->core_mutex);
-		rc = msm_isp_cfg_stats_comp_policy(vfe_dev, arg);
-		mutex_unlock(&vfe_dev->core_mutex);
-		break;
 	case VIDIOC_MSM_ISP_UPDATE_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_update_axi_stream(vfe_dev, arg);
@@ -750,7 +770,8 @@
 	spin_lock_irqsave(&vfe_dev->tasklet_lock, flags);
 	queue_cmd = &vfe_dev->tasklet_queue_cmd[vfe_dev->taskletq_idx];
 	if (queue_cmd->cmd_used) {
-		pr_err("%s: Tasklet queue overflow\n", __func__);
+		pr_err("%s: Tasklet queue overflow: %d\n",
+			__func__, vfe_dev->pdev->id);
 		list_del(&queue_cmd->list);
 	} else {
 		atomic_add(1, &vfe_dev->irq_cnt);
@@ -818,7 +839,6 @@
 
 int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-	uint32_t i;
 	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
 	long rc;
 	ISP_DBG("%s\n", __func__);
@@ -851,9 +871,6 @@
 
 	vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 
-	for (i = 0; i < vfe_dev->hw_info->num_iommu_ctx; i++)
-		vfe_dev->buf_mgr->ops->attach_ctx(vfe_dev->buf_mgr,
-			vfe_dev->iommu_ctx[i]);
 	vfe_dev->buf_mgr->ops->buf_mgr_init(vfe_dev->buf_mgr, "msm_isp", 28);
 
 	memset(&vfe_dev->axi_data, 0, sizeof(struct msm_vfe_axi_shared_data));
@@ -870,7 +887,6 @@
 
 int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-	int i;
 	long rc;
 	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
 	ISP_DBG("%s\n", __func__);
@@ -888,11 +904,6 @@
 		pr_err("%s: halt timeout\n", __func__);
 
 	vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
-
-	for (i = vfe_dev->hw_info->num_iommu_ctx - 1; i >= 0; i--)
-		vfe_dev->buf_mgr->ops->detach_ctx(vfe_dev->buf_mgr,
-			vfe_dev->iommu_ctx[i]);
-
 	vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
 
 	vfe_dev->vfe_open_cnt--;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 7934f26..34b9859 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -43,6 +43,9 @@
 	struct msm_isp_bandwidth_info client_info[MAX_ISP_CLIENT];
 };
 
+uint32_t msm_isp_get_framedrop_period(
+	enum msm_vfe_frame_skip_pattern frame_skip_pattern);
+
 int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client);
 int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
 	uint64_t ab, uint64_t ib);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 90cc61c..962c079 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -175,9 +175,9 @@
 		data |= (csid << 20);
 		break;
 	}
-	if (data)
-		msm_camera_io_w_mb(data, ispif->base +
-			ISPIF_VFE_m_INPUT_SEL(vfe_intf));
+
+	msm_camera_io_w_mb(data, ispif->base +
+		ISPIF_VFE_m_INPUT_SEL(vfe_intf));
 }
 
 static void msm_ispif_enable_crop(struct ispif_device *ispif,
@@ -294,6 +294,58 @@
 	return rc;
 }
 
+static void msm_ispif_select_clk_mux(struct ispif_device *ispif,
+	uint8_t intftype, uint8_t csid, uint8_t vfe_intf)
+{
+	uint32_t data = 0;
+
+	switch (intftype) {
+	case PIX0:
+		data = msm_camera_io_r(ispif->clk_mux_base);
+		data &= ~(0xf << (vfe_intf * 8));
+		data |= (csid << (vfe_intf * 8));
+		msm_camera_io_w(data, ispif->clk_mux_base);
+		break;
+
+	case RDI0:
+		data = msm_camera_io_r(ispif->clk_mux_base +
+			ISPIF_RDI_CLK_MUX_SEL_ADDR);
+		data &= ~(0xf << (vfe_intf * 12));
+		data |= (csid << (vfe_intf * 12));
+		msm_camera_io_w(data, ispif->clk_mux_base +
+			ISPIF_RDI_CLK_MUX_SEL_ADDR);
+		break;
+
+	case PIX1:
+		data = msm_camera_io_r(ispif->clk_mux_base);
+		data &= ~(0xf0 << (vfe_intf * 8));
+		data |= (csid << (4 + (vfe_intf * 8)));
+		msm_camera_io_w(data, ispif->clk_mux_base);
+		break;
+
+	case RDI1:
+		data = msm_camera_io_r(ispif->clk_mux_base +
+			ISPIF_RDI_CLK_MUX_SEL_ADDR);
+		data &= ~(0xf << (4 + (vfe_intf * 12)));
+		data |= (csid << (4 + (vfe_intf * 12)));
+		msm_camera_io_w(data, ispif->clk_mux_base +
+			ISPIF_RDI_CLK_MUX_SEL_ADDR);
+		break;
+
+	case RDI2:
+		data = msm_camera_io_r(ispif->clk_mux_base +
+			ISPIF_RDI_CLK_MUX_SEL_ADDR);
+		data &= ~(0xf << (8 + (vfe_intf * 12)));
+		data |= (csid << (8 + (vfe_intf * 12)));
+		msm_camera_io_w(data, ispif->clk_mux_base +
+			ISPIF_RDI_CLK_MUX_SEL_ADDR);
+		break;
+	}
+	CDBG("%s intftype %d data %x\n", __func__, intftype, data);
+	mb();
+	return;
+}
+
 static uint16_t msm_ispif_get_cids_mask_from_cfg(
 	struct msm_ispif_params_entry *entry)
 {
@@ -358,6 +410,10 @@
 			return -EINVAL;
 		}
 
+		if (ispif->csid_version >= CSID_VERSION_V3)
+				msm_ispif_select_clk_mux(ispif, intftype,
+				params->entries[i].csid, vfe_intf);
+
 		rc = msm_ispif_validate_intf_status(ispif, intftype, vfe_intf);
 		if (rc) {
 			pr_err("%s:validate_intf_status failed, rc = %d\n",
@@ -716,6 +772,22 @@
 
 	ispif->csid_version = csid_version;
 
+	if (ispif->csid_version >= CSID_VERSION_V3) {
+		if (!ispif->clk_mux_mem || !ispif->clk_mux_io) {
+			pr_err("%s csi clk mux mem %p io %p\n", __func__,
+				ispif->clk_mux_mem, ispif->clk_mux_io);
+			rc = -ENOMEM;
+			return rc;
+		}
+		ispif->clk_mux_base = ioremap(ispif->clk_mux_mem->start,
+			resource_size(ispif->clk_mux_mem));
+		if (!ispif->clk_mux_base) {
+			pr_err("%s: clk_mux_mem ioremap failed\n", __func__);
+			rc = -ENOMEM;
+			return rc;
+		}
+	}
+
 	ispif->base = ioremap(ispif->mem->start,
 		resource_size(ispif->mem));
 	if (!ispif->base) {
@@ -771,6 +843,8 @@
 
 	iounmap(ispif->base);
 
+	iounmap(ispif->clk_mux_base);
+
 	ispif->ispif_state = ISPIF_POWER_DOWN;
 }
 
@@ -942,6 +1016,16 @@
 		rc = -EBUSY;
 		goto error;
 	}
+	ispif->clk_mux_mem = platform_get_resource_byname(pdev,
+		IORESOURCE_MEM, "csi_clk_mux");
+	if (ispif->clk_mux_mem) {
+		ispif->clk_mux_io = request_mem_region(
+			ispif->clk_mux_mem->start,
+			resource_size(ispif->clk_mux_mem),
+			ispif->clk_mux_mem->name);
+		if (!ispif->clk_mux_io)
+			pr_err("%s: no valid csi_mux region\n", __func__);
+	}
 
 	ispif->pdev = pdev;
 	ispif->ispif_state = ISPIF_POWER_DOWN;
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
index fae7a38..faa32aa 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
@@ -42,9 +42,12 @@
 	struct platform_device *pdev;
 	struct msm_sd_subdev msm_sd;
 	struct resource *mem;
+	struct resource *clk_mux_mem;
 	struct resource *irq;
 	struct resource *io;
+	struct resource *clk_mux_io;
 	void __iomem *base;
+	void __iomem *clk_mux_base;
 	struct mutex mutex;
 	uint8_t start_ack_pending;
 	uint32_t csid_version;
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index 9f8b2fa..6396486 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -50,6 +50,8 @@
 
 
 
+/* CSID CLK MUX SEL REGISTERS */
+#define ISPIF_RDI_CLK_MUX_SEL_ADDR              0x8
 
 /*ISPIF RESET BITS*/
 #define VFE_CLK_DOMAIN_RST                 BIT(31)
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 5e61a4d..c805c3d 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -46,6 +46,9 @@
 #define ISPIF_VFE_m_RDI_INTF_n_STATUS(m, n)      (0x2D0 + ISPIF_VFE(m) + 4*(n))
 #define ISPIF_VFE_m_3D_DESKEW_SIZE(m)            (0x2E4 + ISPIF_VFE(m))
 
+/* CSID CLK MUX SEL REGISTERS */
+#define ISPIF_RDI_CLK_MUX_SEL_ADDR               0x8
+
 /*ISPIF RESET BITS*/
 #define VFE_CLK_DOMAIN_RST                       BIT(31)
 #define PIX_1_CLK_DOMAIN_RST                     BIT(30)
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index fbd4a2e..33eaa69 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -185,49 +185,15 @@
 	{"csi_pclk", -1},
 };
 
-static struct msm_cam_clk_info csid0_8974_clk_info[] = {
+static struct msm_cam_clk_info csid_8974_clk_info[] = {
 	{"camss_top_ahb_clk", -1},
 	{"ispif_ahb_clk", -1},
-	{"csi0_ahb_clk", -1},
-	{"csi0_src_clk", 200000000},
-	{"csi0_clk", -1},
-	{"csi0_phy_clk", -1},
-	{"csi0_pix_clk", -1},
-	{"csi0_rdi_clk", -1},
-};
-
-static struct msm_cam_clk_info csid1_8974_clk_info[] = {
-	{"csi1_ahb_clk", -1},
-	{"csi1_src_clk", 200000000},
-	{"csi1_clk", -1},
-	{"csi1_phy_clk", -1},
-	{"csi1_pix_clk", -1},
-	{"csi1_rdi_clk", -1},
-};
-
-static struct msm_cam_clk_info csid2_8974_clk_info[] = {
-	{"csi2_ahb_clk", -1},
-	{"csi2_src_clk", 200000000},
-	{"csi2_clk", -1},
-	{"csi2_phy_clk", -1},
-	{"csi2_pix_clk", -1},
-	{"csi2_rdi_clk", -1},
-};
-
-static struct msm_cam_clk_info csid3_8974_clk_info[] = {
-	{"csi3_ahb_clk", -1},
-	{"csi3_src_clk", 200000000},
-	{"csi3_clk", -1},
-	{"csi3_phy_clk", -1},
-	{"csi3_pix_clk", -1},
-	{"csi3_rdi_clk", -1},
-};
-
-static struct msm_cam_clk_setting csid_8974_clk_info[] = {
-	{&csid0_8974_clk_info[0], ARRAY_SIZE(csid0_8974_clk_info)},
-	{&csid1_8974_clk_info[0], ARRAY_SIZE(csid1_8974_clk_info)},
-	{&csid2_8974_clk_info[0], ARRAY_SIZE(csid2_8974_clk_info)},
-	{&csid3_8974_clk_info[0], ARRAY_SIZE(csid3_8974_clk_info)},
+	{"csi_ahb_clk", -1},
+	{"csi_src_clk", 200000000},
+	{"csi_clk", -1},
+	{"csi_phy_clk", -1},
+	{"csi_pix_clk", -1},
+	{"csi_rdi_clk", -1},
 };
 
 static struct camera_vreg_t csid_8960_vreg_info[] = {
@@ -241,7 +207,6 @@
 static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
 {
 	int rc = 0;
-	uint8_t core_id = 0;
 
 	if (!csid_version) {
 		pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
@@ -306,26 +271,14 @@
 		}
 
 		rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
-			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
-			csid_8974_clk_info[0].num_clk_info, 1);
+			csid_8974_clk_info, csid_dev->csid_clk,
+			ARRAY_SIZE(csid_8974_clk_info), 1);
 		if (rc < 0) {
 			pr_err("%s: clock enable failed\n", __func__);
-			goto csid0_clk_enable_failed;
-		}
-		core_id = csid_dev->pdev->id;
-		if (core_id) {
-			rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
-				csid_8974_clk_info[core_id].clk_info,
-				csid_dev->csid_clk,
-				csid_8974_clk_info[core_id].num_clk_info, 1);
-			if (rc < 0) {
-				pr_err("%s: clock enable failed\n",
-					__func__);
-				goto clk_enable_failed;
-			}
+			goto clk_enable_failed;
 		}
 	}
-
+		CDBG("%s:%d called\n", __func__, __LINE__);
 	csid_dev->hw_version =
 		msm_camera_io_r(csid_dev->base + CSID_HW_VERSION_ADDR);
 	CDBG("%s:%d called csid_dev->hw_version %x\n", __func__, __LINE__,
@@ -341,12 +294,6 @@
 	return rc;
 
 clk_enable_failed:
-	if (CSID_VERSION >= CSID_VERSION_V3) {
-		msm_cam_clk_enable(&csid_dev->pdev->dev,
-			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
-			csid_8974_clk_info[0].num_clk_info, 0);
-	}
-csid0_clk_enable_failed:
 	if (CSID_VERSION <= CSID_VERSION_V2) {
 		msm_camera_enable_vreg(&csid_dev->pdev->dev,
 			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
@@ -375,7 +322,6 @@
 static int msm_csid_release(struct csid_device *csid_dev)
 {
 	uint32_t irq;
-	uint8_t core_id = 0;
 
 	if (csid_dev->csid_state != CSID_POWER_UP) {
 		pr_err("%s: csid invalid state %d\n", __func__,
@@ -401,16 +347,8 @@
 			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
 			NULL, 0, &csid_dev->csi_vdd, 0);
 	} else if (csid_dev->hw_version >= CSID_VERSION_V3) {
-		core_id = csid_dev->pdev->id;
-		if (core_id)
-			msm_cam_clk_enable(&csid_dev->pdev->dev,
-				csid_8974_clk_info[core_id].clk_info,
-				csid_dev->csid_clk,
-				csid_8974_clk_info[core_id].num_clk_info, 0);
-
-		msm_cam_clk_enable(&csid_dev->pdev->dev,
-			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
-			csid_8974_clk_info[0].num_clk_info, 0);
+		msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8974_clk_info,
+			csid_dev->csid_clk, ARRAY_SIZE(csid_8974_clk_info), 0);
 
 		msm_camera_enable_vreg(&csid_dev->pdev->dev,
 			csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
index 7ae1392..fd4db79 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
@@ -38,7 +38,6 @@
 	uint32_t hw_version;
 	enum msm_csid_state_t csid_state;
 
-	struct clk *csid0_clk[11];
 	struct clk *csid_clk[11];
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index df3ee60..7d3a1fc 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -43,14 +43,15 @@
 	uint8_t lane_cnt = 0;
 	uint16_t lane_mask = 0;
 	void __iomem *csiphybase;
+	uint8_t csiphy_id = csiphy_dev->pdev->id;
 	csiphybase = csiphy_dev->base;
 	if (!csiphybase) {
 		pr_err("%s: csiphybase NULL\n", __func__);
 		return -EINVAL;
 	}
 
-	csiphy_dev->lane_mask[csiphy_dev->pdev->id] |= csiphy_params->lane_mask;
-	lane_mask = csiphy_dev->lane_mask[csiphy_dev->pdev->id];
+	csiphy_dev->lane_mask[csiphy_id] |= csiphy_params->lane_mask;
+	lane_mask = csiphy_dev->lane_mask[csiphy_id];
 	lane_cnt = csiphy_params->lane_cnt;
 	if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
 		pr_err("%s: unsupported lane cnt %d\n",
@@ -58,11 +59,28 @@
 		return rc;
 	}
 
-	CDBG("%s csiphy_params, mask = %x, cnt = %d, settle cnt = %x\n",
+	CDBG("%s csiphy_params, mask = %x cnt = %d settle cnt = %x csid %d\n",
 		__func__,
 		csiphy_params->lane_mask,
 		csiphy_params->lane_cnt,
-		csiphy_params->settle_cnt);
+		csiphy_params->settle_cnt,
+		csiphy_params->csid_core);
+
+	if (csiphy_dev->hw_version >= CSIPHY_VERSION_V3) {
+		val = msm_camera_io_r(csiphy_dev->clk_mux_base);
+		if (csiphy_params->combo_mode &&
+			(csiphy_params->lane_mask & 0x18)) {
+			val &= ~0xf0;
+			val |= csiphy_params->csid_core << 4;
+		} else {
+			val &= ~0xf;
+			val |= csiphy_params->csid_core;
+		}
+		msm_camera_io_w(val, csiphy_dev->clk_mux_base);
+		CDBG("%s clk mux addr %p val 0x%x\n", __func__,
+			csiphy_dev->clk_mux_base, val);
+		mb();
+	}
 	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
 	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
 
@@ -204,6 +222,22 @@
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8960_clk_info), 1);
 	} else {
+		if (!csiphy_dev->clk_mux_mem || !csiphy_dev->clk_mux_io) {
+			pr_err("%s clk mux mem %p io %p\n", __func__,
+				csiphy_dev->clk_mux_mem,
+				csiphy_dev->clk_mux_io);
+			rc = -ENOMEM;
+			return rc;
+		}
+		csiphy_dev->clk_mux_base = ioremap(
+			csiphy_dev->clk_mux_mem->start,
+			resource_size(csiphy_dev->clk_mux_mem));
+		if (!csiphy_dev->clk_mux_base) {
+			pr_err("%s: ERROR %d\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			return rc;
+		}
+
 		CDBG("%s:%d called\n", __func__, __LINE__);
 		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
@@ -269,12 +303,31 @@
 	}
 	CDBG("%s:%d called\n", __func__, __LINE__);
 
+
 	if (CSIPHY_VERSION < CSIPHY_VERSION_V3) {
 		CDBG("%s:%d called\n", __func__, __LINE__);
 		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8960_clk_info), 1);
 	} else {
+
+		if (!csiphy_dev->clk_mux_mem || !csiphy_dev->clk_mux_io) {
+			pr_err("%s clk mux mem %p io %p\n", __func__,
+				csiphy_dev->clk_mux_mem,
+				csiphy_dev->clk_mux_io);
+			rc = -ENOMEM;
+			return rc;
+		}
+
+		csiphy_dev->clk_mux_base = ioremap(
+			csiphy_dev->clk_mux_mem->start,
+			resource_size(csiphy_dev->clk_mux_mem));
+		if (!csiphy_dev->clk_mux_base) {
+			pr_err("%s: ERROR %d\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			return rc;
+		}
+
 		CDBG("%s:%d called\n", __func__, __LINE__);
 		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
@@ -359,14 +412,16 @@
 
 	disable_irq(csiphy_dev->irq->start);
 
-	if (CSIPHY_VERSION < CSIPHY_VERSION_V3)
+	if (CSIPHY_VERSION < CSIPHY_VERSION_V3) {
 		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8960_clk_info), 0);
-	else
+	} else {
 		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8974_clk_info), 0);
+			iounmap(csiphy_dev->clk_mux_base);
+	}
 
 	iounmap(csiphy_dev->base);
 	csiphy_dev->base = NULL;
@@ -426,20 +481,23 @@
 	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_LNCK_CFG2_ADDR);
 	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
 
-	if (CSIPHY_VERSION < CSIPHY_VERSION_V3)
+	if (CSIPHY_VERSION < CSIPHY_VERSION_V3) {
 		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8960_clk_info), 0);
-	else
+	} else {
 		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8974_clk_info), 0);
+			iounmap(csiphy_dev->clk_mux_base);
+	}
 
 	iounmap(csiphy_dev->base);
 	csiphy_dev->base = NULL;
 	csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
 	return 0;
 }
+
 #endif
 
 static long msm_csiphy_cmd(struct csiphy_device *csiphy_dev, void *arg)
@@ -588,6 +646,17 @@
 	}
 	disable_irq(new_csiphy_dev->irq->start);
 
+	new_csiphy_dev->clk_mux_mem = platform_get_resource_byname(pdev,
+		IORESOURCE_MEM, "csiphy_clk_mux");
+	if (new_csiphy_dev->clk_mux_mem) {
+		new_csiphy_dev->clk_mux_io = request_mem_region(
+			new_csiphy_dev->clk_mux_mem->start,
+			resource_size(new_csiphy_dev->clk_mux_mem),
+			new_csiphy_dev->clk_mux_mem->name);
+		if (!new_csiphy_dev->clk_mux_io)
+			pr_err("%s: ERROR %d\n", __func__, __LINE__);
+	}
+
 	new_csiphy_dev->pdev = pdev;
 	new_csiphy_dev->msm_sd.sd.internal_ops = &msm_csiphy_internal_ops;
 	new_csiphy_dev->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
index e19be34..a11b958 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
@@ -32,9 +32,12 @@
 	struct msm_sd_subdev msm_sd;
 	struct v4l2_subdev subdev;
 	struct resource *mem;
+	struct resource *clk_mux_mem;
 	struct resource *irq;
 	struct resource *io;
+	struct resource *clk_mux_io;
 	void __iomem *base;
+	void __iomem *clk_mux_base;
 	struct mutex mutex;
 	uint32_t hw_version;
 	enum msm_csiphy_state_t csiphy_state;
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 14d1197..bb3a797 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
@@ -25,6 +25,9 @@
 /* Length of mandatory fields that must exist in header of video PES */
 #define PES_MANDATORY_FIELDS_LEN			9
 
+/* Index of first byte in TS packet holding STC */
+#define STC_LOCATION_IDX			188
+
 #define MAX_PES_LENGTH	(SZ_64K)
 
 #define MAX_TS_PACKETS_FOR_SDMX_PROCESS	(500)
@@ -2202,6 +2205,14 @@
 	size_t len = 0;
 	struct dmx_pts_dts_info *pts_dts;
 
+	if (meta_data->packet_type == DMX_PES_PACKET) {
+		pts_dts = &meta_data->info.pes.pts_dts_info;
+		data->buf.stc = meta_data->info.pes.stc;
+	} else {
+		pts_dts = &meta_data->info.framing.pts_dts_info;
+		data->buf.stc = meta_data->info.framing.stc;
+	}
+
 	pts_dts = meta_data->packet_type == DMX_PES_PACKET ?
 		&meta_data->info.pes.pts_dts_info :
 		&meta_data->info.framing.pts_dts_info;
@@ -2313,6 +2324,7 @@
 		packet.raw_data_offset = feed_data->frame_offset;
 		meta_data.info.framing.pattern_type =
 			feed_data->last_framing_match_type;
+		meta_data.info.framing.stc = feed_data->last_framing_match_stc;
 
 		mpq_streambuffer_get_buffer_handle(stream_buffer,
 			0, /* current write buffer handle */
@@ -2385,6 +2397,7 @@
 		mpq_dmx_save_pts_dts(feed_data);
 
 		meta_data.packet_type = DMX_PES_PACKET;
+		meta_data.info.pes.stc = feed_data->prev_stc;
 
 		mpq_dmx_update_decoder_stat(mpq_demux);
 
@@ -2411,7 +2424,8 @@
 
 static int mpq_dmx_process_video_packet_framing(
 			struct dvb_demux_feed *feed,
-			const u8 *buf)
+			const u8 *buf,
+			u64 curr_stc)
 {
 	int bytes_avail;
 	u32 ts_payload_offset;
@@ -2596,7 +2610,8 @@
 	 * pass data to decoder only after sequence header
 	 * or equivalent is found. Otherwise the data is dropped.
 	 */
-	if (!(feed_data->found_sequence_header_pattern)) {
+	if (!feed_data->found_sequence_header_pattern) {
+		feed_data->prev_stc = curr_stc;
 		spin_unlock(&feed_data->video_buffer_lock);
 		return 0;
 	}
@@ -2699,6 +2714,12 @@
 					framing_res.info[i].type;
 				feed_data->last_pattern_offset =
 					framing_res.info[i].offset;
+				if (framing_res.info[i].used_prefix_size)
+					feed_data->last_framing_match_stc =
+						feed_data->prev_stc;
+				else
+					feed_data->last_framing_match_stc =
+						curr_stc;
 				continue;
 			}
 			/*
@@ -2744,6 +2765,8 @@
 			packet.raw_data_offset = feed_data->frame_offset;
 			meta_data.info.framing.pattern_type =
 				feed_data->last_framing_match_type;
+			meta_data.info.framing.stc =
+				feed_data->last_framing_match_stc;
 
 			mpq_streambuffer_get_buffer_handle(
 				stream_buffer,
@@ -2784,8 +2807,13 @@
 			framing_res.info[i].type;
 		feed_data->last_pattern_offset =
 			framing_res.info[i].offset;
+		if (framing_res.info[i].used_prefix_size)
+			feed_data->last_framing_match_stc = feed_data->prev_stc;
+		else
+			feed_data->last_framing_match_stc = curr_stc;
 	}
 
+	feed_data->prev_stc = curr_stc;
 	feed_data->first_prefix_size = 0;
 
 	if (pending_data_len) {
@@ -2810,7 +2838,8 @@
 
 static int mpq_dmx_process_video_packet_no_framing(
 			struct dvb_demux_feed *feed,
-			const u8 *buf)
+			const u8 *buf,
+			u64 curr_stc)
 {
 	int bytes_avail;
 	u32 ts_payload_offset;
@@ -2886,6 +2915,7 @@
 				mpq_dmx_save_pts_dts(feed_data);
 
 				meta_data.packet_type = DMX_PES_PACKET;
+				meta_data.info.pes.stc = feed_data->prev_stc;
 
 				mpq_dmx_update_decoder_stat(mpq_demux);
 
@@ -2928,6 +2958,8 @@
 		} else {
 			feed->pusi_seen = 1;
 		}
+
+		feed_data->prev_stc = curr_stc;
 	}
 
 	/*
@@ -3077,10 +3109,25 @@
 			struct dvb_demux_feed *feed,
 			const u8 *buf)
 {
+	u64 curr_stc;
+	struct mpq_demux *mpq_demux = feed->demux->priv;
+
+	if ((mpq_demux->source >= DMX_SOURCE_DVR0) &&
+		(mpq_demux->demux.tsp_format != DMX_TSP_FORMAT_192_TAIL)) {
+		curr_stc = 0;
+	} else {
+		curr_stc = buf[STC_LOCATION_IDX + 2] << 16;
+		curr_stc += buf[STC_LOCATION_IDX + 1] << 8;
+		curr_stc += buf[STC_LOCATION_IDX];
+		curr_stc *= 256; /* convert from 105.47 KHZ to 27MHz */
+	}
+
 	if (mpq_dmx_info.decoder_framing)
-		return mpq_dmx_process_video_packet_no_framing(feed, buf);
+		return mpq_dmx_process_video_packet_no_framing(feed, buf,
+				curr_stc);
 	else
-		return mpq_dmx_process_video_packet_framing(feed, buf);
+		return mpq_dmx_process_video_packet_framing(feed, buf,
+				curr_stc);
 }
 EXPORT_SYMBOL(mpq_dmx_process_video_packet);
 
@@ -3151,9 +3198,9 @@
 		(mpq_demux->demux.tsp_format != DMX_TSP_FORMAT_192_TAIL)) {
 		stc = 0;
 	} else {
-		stc = buf[190] << 16;
-		stc += buf[189] << 8;
-		stc += buf[188];
+		stc = buf[STC_LOCATION_IDX + 2] << 16;
+		stc += buf[STC_LOCATION_IDX + 1] << 8;
+		stc += buf[STC_LOCATION_IDX];
 		stc *= 256; /* convert from 105.47 KHZ to 27MHz */
 	}
 
@@ -4190,6 +4237,9 @@
 		pes_header = (struct pes_packet_header *)
 			&metadata_buf[pes_header_offset];
 		meta_data.packet_type = DMX_PES_PACKET;
+		/* TODO - set to real STC when SDMX supports it */
+		meta_data.info.pes.stc = 0;
+
 		if (pes_header->pts_dts_flag & 0x2) {
 			meta_data.info.pes.pts_dts_info.pts_exist = 1;
 			meta_data.info.pes.pts_dts_info.pts =
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 80b5428..899ef4c 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
@@ -244,6 +244,8 @@
  * reported for this frame.
  * @last_framing_match_type: Used for saving the type of
  * the previous pattern match found in this video feed.
+ * @last_framing_match_stc: Used for saving the STC attached to TS packet
+ * of the previous pattern match found in this video feed.
  * @found_sequence_header_pattern: Flag used to note that an MPEG-2
  * Sequence Header, H.264 SPS or VC-1 Sequence Header pattern
  * (whichever is relevant according to the video standard) had already
@@ -272,6 +274,7 @@
  * buffer space.
  * @last_pkt_index: used to save the last streambuffer packet index reported in
  * a new elementary stream data event.
+ * @prev_stc: STC attached to the previous video TS packet
  */
 struct mpq_video_feed_info {
 	struct mpq_streambuffer *video_buffer;
@@ -289,6 +292,7 @@
 	u32 last_pattern_offset;
 	u32 pending_pattern_len;
 	u64 last_framing_match_type;
+	u64 last_framing_match_stc;
 	int found_sequence_header_pattern;
 	struct dvb_dmx_video_prefix_size_masks prefix_size;
 	u32 first_prefix_size;
@@ -303,6 +307,7 @@
 	u32 ts_packets_num;
 	u32 ts_dropped_bytes;
 	int last_pkt_index;
+	u64 prev_stc;
 };
 
 /**
diff --git a/drivers/media/platform/msm/dvb/include/mpq_adapter.h b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
index 19abbbe..a2ade18 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_adapter.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
@@ -64,11 +64,17 @@
 
 	/** PTS/DTS information */
 	struct dmx_pts_dts_info pts_dts_info;
+
+	/** STC value attached to first TS packet holding the pattern */
+	u64 stc;
 };
 
 struct dmx_pes_packet_info {
 	/** PTS/DTS information */
 	struct dmx_pts_dts_info pts_dts_info;
+
+	/** STC value attached to first TS packet holding the PES */
+	u64 stc;
 };
 
 struct dmx_marker_info {
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 2c29e61..5f47ae1 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -762,7 +762,7 @@
 	struct v4l2_ctrl *ctrl = NULL;
 	u32 extradata = 0;
 	if (!q || !q->drv_priv) {
-		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input\n");
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index d925de3..fb25072 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1667,6 +1667,7 @@
 			core->state == VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
 				"Core is in bad state can't change the state");
+		rc = -EINVAL;
 		goto exit;
 	}
 	flipped_state = get_flipped_state(inst->state, state);
@@ -1900,8 +1901,14 @@
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
 	}
-	hdev = inst->core->device;
 
+	if (inst->state == MSM_VIDC_CORE_INVALID ||
+			inst->core->state == VIDC_CORE_INVALID) {
+		dprintk(VIDC_ERR,
+				"Core is in bad state can't query get_bufreqs()");
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 	mutex_lock(&inst->sync_lock);
 	if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
 		dprintk(VIDC_ERR,
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index dbb4f5e..73cae32 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1571,6 +1571,7 @@
 	int id;
 	int table_idx;
 	u32 val;
+	unsigned long flags;
 
 	struct sps_connect *config;
 	struct tspp_device *pdev;
@@ -1591,6 +1592,15 @@
 	if (!channel->used)
 		return 0;
 
+	/*
+	 * Need to protect access to used and waiting fields, as they are
+	 * used by the tasklet which is invoked from interrupt context
+	 */
+	spin_lock_irqsave(&pdev->spinlock, flags);
+	channel->used = 0;
+	channel->waiting = NULL;
+	spin_unlock_irqrestore(&pdev->spinlock, flags);
+
 	if (channel->expiration_period_ms)
 		del_timer(&channel->expiration_timer);
 
@@ -1644,9 +1654,7 @@
 	channel->buffer_count = 0;
 	channel->data = NULL;
 	channel->read = NULL;
-	channel->waiting = NULL;
 	channel->locked = NULL;
-	channel->used = 0;
 
 	if (tspp_channels_in_use(pdev) == 0) {
 		wake_unlock(&pdev->wake_lock);
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 4e12bb7..147e378 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1127,6 +1127,33 @@
 }
 #endif
 
+static inline unsigned long get_vm_size(struct vm_area_struct *vma)
+{
+	return vma->vm_end - vma->vm_start;
+}
+
+static inline resource_size_t get_vm_offset(struct vm_area_struct *vma)
+{
+	return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT;
+}
+
+/*
+ * Set a new vm offset.
+ *
+ * Verify that the incoming offset really works as a page offset,
+ * and that the offset and size fit in a resource_size_t.
+ */
+static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off)
+{
+	pgoff_t pgoff = off >> PAGE_SHIFT;
+	if (off != (resource_size_t) pgoff << PAGE_SHIFT)
+		return -EINVAL;
+	if (off + get_vm_size(vma) - 1 < off)
+		return -EINVAL;
+	vma->vm_pgoff = pgoff;
+	return 0;
+}
+
 /*
  * set up a mapping for shared memory segments
  */
@@ -1136,20 +1163,29 @@
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
 	struct map_info *map = mtd->priv;
-	unsigned long start;
-	unsigned long off;
-	u32 len;
+	resource_size_t start, off;
+	unsigned long len, vma_len;
 
 	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
-		off = vma->vm_pgoff << PAGE_SHIFT;
+		off = get_vm_offset(vma);
 		start = map->phys;
 		len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
 		start &= PAGE_MASK;
-		if ((vma->vm_end - vma->vm_start + off) > len)
+		vma_len = get_vm_size(vma);
+
+		/* Overflow in off+len? */
+		if (vma_len + off < off)
+			return -EINVAL;
+		/* Does it fit in the mapping? */
+		if (vma_len + off > len)
 			return -EINVAL;
 
 		off += start;
-		vma->vm_pgoff = off >> PAGE_SHIFT;
+		/* Did that overflow? */
+		if (off < start)
+			return -EINVAL;
+		if (set_vm_offset(vma, off) < 0)
+			return -EINVAL;
 		vma->vm_flags |= VM_IO | VM_RESERVED;
 
 #ifdef pgprot_noncached
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 4b5f0a2..3a93c15 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -205,6 +205,7 @@
 	smsm_change_state(SMSM_APPS_STATE,
 				clear_bit & SMSM_A2_POWER_CONTROL_ACK,
 				~clear_bit & SMSM_A2_POWER_CONTROL_ACK);
+	IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_apps_acks);
 	clear_bit = ~clear_bit;
 }
 
@@ -216,10 +217,13 @@
 	if (a2_mux_ctx->bam_dmux_uplink_vote == vote)
 		IPADBG("%s: warning - duplicate power vote\n", __func__);
 	a2_mux_ctx->bam_dmux_uplink_vote = vote;
-	if (vote)
+	if (vote) {
 		smsm_change_state(SMSM_APPS_STATE, 0, SMSM_A2_POWER_CONTROL);
-	else
+		IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_on_reqs_out);
+	} else {
 		smsm_change_state(SMSM_APPS_STATE, SMSM_A2_POWER_CONTROL, 0);
+		IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_off_reqs_out);
+	}
 }
 
 static inline void ul_powerdown(void)
@@ -634,12 +638,14 @@
 	last_processed_state = new_state & SMSM_A2_POWER_CONTROL;
 	if (new_state & SMSM_A2_POWER_CONTROL) {
 		IPADBG("%s: MODEM PWR CTRL 1\n", __func__);
+		IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_on_reqs_in);
 		grab_wakelock();
 		(void) connect_to_bam();
 		queue_work(a2_mux_ctx->a2_mux_tx_workqueue,
 			   &a2_mux_ctx->kickoff_ul_request_resource);
 	} else if (!(new_state & SMSM_A2_POWER_CONTROL)) {
 		IPADBG("%s: MODEM PWR CTRL 0\n", __func__);
+		IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_off_reqs_in);
 		(void) disconnect_to_bam();
 		release_wakelock();
 	} else {
@@ -653,6 +659,7 @@
 {
 	IPADBG("%s: 0x%08x -> 0x%08x\n", __func__, old_state,
 			new_state);
+	IPA_STATS_INC_CNT(ipa_ctx->stats.a2_power_modem_acks);
 	complete_all(&a2_mux_ctx->ul_wakeup_ack_completion);
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_debugfs.c
index bc5aa6f..b1ac04c 100644
--- a/drivers/platform/msm/ipa/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_debugfs.c
@@ -556,7 +556,13 @@
 			"x_intr_repost=%u\n"
 			"rx_q_len=%u\n"
 			"act_clnt=%u\n"
-			"con_clnt_bmap=0x%x\n",
+			"con_clnt_bmap=0x%x\n"
+			"a2_power_on_reqs_in=%u\n"
+			"a2_power_on_reqs_out=%u\n"
+			"a2_power_off_reqs_in=%u\n"
+			"a2_power_off_reqs_out=%u\n"
+			"a2_power_modem_acks=%u\n"
+			"a2_power_apps_acks=%u\n",
 			ipa_ctx->stats.tx_sw_pkts,
 			ipa_ctx->stats.tx_hw_pkts,
 			ipa_ctx->stats.rx_pkts,
@@ -564,7 +570,13 @@
 			ipa_ctx->stats.x_intr_repost,
 			ipa_ctx->stats.rx_q_len,
 			ipa_ctx->ipa_active_clients,
-			connect);
+			connect,
+			ipa_ctx->stats.a2_power_on_reqs_in,
+			ipa_ctx->stats.a2_power_on_reqs_out,
+			ipa_ctx->stats.a2_power_off_reqs_in,
+			ipa_ctx->stats.a2_power_off_reqs_out,
+			ipa_ctx->stats.a2_power_modem_acks,
+			ipa_ctx->stats.a2_power_apps_acks);
 	cnt += nbytes;
 
 	for (i = 0; i < MAX_NUM_EXCP; i++) {
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index a03ba16..1de72fe 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -531,6 +531,12 @@
 	u32 rx_q_len;
 	u32 msg_w[IPA_EVENT_MAX];
 	u32 msg_r[IPA_EVENT_MAX];
+	u32 a2_power_on_reqs_in;
+	u32 a2_power_on_reqs_out;
+	u32 a2_power_off_reqs_in;
+	u32 a2_power_off_reqs_out;
+	u32 a2_power_modem_acks;
+	u32 a2_power_apps_acks;
 };
 
 /**
diff --git a/drivers/tty/smux_ctl.c b/drivers/tty/smux_ctl.c
index 2e091cc..1b3a7abe 100644
--- a/drivers/tty/smux_ctl.c
+++ b/drivers/tty/smux_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -940,6 +940,7 @@
 static int smux_ctl_remove(struct platform_device *pdev)
 {
 	int i;
+	int ret;
 
 	SMUXCTL_DBG(SMUX_CTL_MODULE_NAME ": %s Begins\n", __func__);
 
@@ -950,6 +951,13 @@
 		devp->abort_wait = 1;
 		wake_up(&devp->write_wait_queue);
 		wake_up(&devp->read_wait_queue);
+
+		if (atomic_read(&devp->ref_count)) {
+			ret = msm_smux_close(devp->id);
+			if (ret)
+				pr_err("%s: unable to close ch %d, ret %d\n",
+						__func__, devp->id, ret);
+		}
 		mutex_unlock(&devp->dev_lock);
 
 		/* Empty RX queue */
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 6fca910..7101d56 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -445,7 +445,8 @@
 	int n = hw_ep_bit(num, dir);
 	struct ci13xxx_ep *mEp = &_udc->ci13xxx_ep[n];
 
-	if (_udc->skip_flush || list_empty(&mEp->qh.queue))
+	/* Flush ep0 even when queue is empty */
+	if (_udc->skip_flush || (num && list_empty(&mEp->qh.queue)))
 		return 0;
 
 	start = ktime_get();
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index 3b1843b..3355e19 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -139,9 +139,6 @@
  * @out_desc: USB OUT endpoint descriptor struct
  * @read_pool: List of requests used for Rx (OUT ep)
  * @write_pool: List of requests used for Tx (IN ep)
- * @config_work: Work item schedule after interface is configured to notify
- *               CONNECT event to diag char driver and updating product id
- *               and serial number to MODEM/IMEM.
  * @lock: Spinlock to proctect read_pool, write_pool lists
  * @cdev: USB composite device struct
  * @ch: USB diag channel
@@ -153,7 +150,6 @@
 	struct usb_ep *in;
 	struct list_head read_pool;
 	struct list_head write_pool;
-	struct work_struct config_work;
 	spinlock_t lock;
 	unsigned configured;
 	struct usb_composite_dev *cdev;
@@ -176,21 +172,20 @@
 	return container_of(f, struct diag_context, function);
 }
 
-static void usb_config_work_func(struct work_struct *work)
+static void diag_update_pid_and_serial_num(struct diag_context *ctxt)
 {
-	struct diag_context *ctxt = container_of(work,
-			struct diag_context, config_work);
 	struct usb_composite_dev *cdev = ctxt->cdev;
 	struct usb_gadget_strings *table;
 	struct usb_string *s;
 
-	if (!ctxt->ch)
+	if (!ctxt->update_pid_and_serial_num)
 		return;
 
-	if (ctxt->ch->notify)
-		ctxt->ch->notify(ctxt->ch->priv, USB_DIAG_CONNECT, NULL);
-
-	if (!ctxt->update_pid_and_serial_num)
+	/*
+	 * update pid and serail number to dload only if diag
+	 * interface is zeroth interface.
+	 */
+	if (intf_desc.bInterfaceNumber)
 		return;
 
 	/* pass on product id and serial number to dload */
@@ -612,7 +607,6 @@
 		usb_ep_disable(dev->in);
 		return rc;
 	}
-	schedule_work(&dev->config_work);
 
 	dev->dpkts_tolaptop = 0;
 	dev->dpkts_tomodem = 0;
@@ -622,6 +616,9 @@
 	dev->configured = 1;
 	spin_unlock_irqrestore(&dev->lock, flags);
 
+	if (dev->ch->notify)
+		dev->ch->notify(dev->ch->priv, USB_DIAG_CONNECT, NULL);
+
 	return rc;
 }
 
@@ -699,6 +696,7 @@
 		if (!f->ss_descriptors)
 			goto fail;
 	}
+	diag_update_pid_and_serial_num(ctxt);
 	return 0;
 fail:
 	if (f->ss_descriptors)
@@ -761,7 +759,6 @@
 	spin_lock_init(&dev->lock);
 	INIT_LIST_HEAD(&dev->read_pool);
 	INIT_LIST_HEAD(&dev->write_pool);
-	INIT_WORK(&dev->config_work, usb_config_work_func);
 
 	ret = usb_add_function(c, &dev->function);
 	if (ret) {
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 51f0e50..46a6bba 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -849,6 +849,10 @@
 	usb_ep_free_request(ecm->notify, ecm->notify_req);
 
 	ecm_qc_string_defs[1].s = NULL;
+
+	if (ecm->xport == USB_GADGET_XPORT_BAM2BAM_IPA)
+		ecm_ipa_cleanup(ipa_params.ipa_priv);
+
 	kfree(ecm);
 }
 
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 4a085aa..7674d88 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -78,6 +78,7 @@
 	struct clk		*alt_core_clk;
 	struct clk		*phy_clk;
 	struct clk		*cal_clk;
+	struct clk		*inactivity_clk;
 	struct regulator	*hsic_vddcx;
 	struct regulator	*hsic_gdsc;
 	atomic_t		async_int;
@@ -575,6 +576,8 @@
 		clk_disable_unprepare(mehci->phy_clk);
 		clk_disable_unprepare(mehci->cal_clk);
 		clk_disable_unprepare(mehci->ahb_clk);
+		if (!IS_ERR(mehci->inactivity_clk))
+			clk_disable_unprepare(mehci->inactivity_clk);
 
 		ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
 		if (ret) {
@@ -596,6 +599,8 @@
 		clk_prepare_enable(mehci->phy_clk);
 		clk_prepare_enable(mehci->cal_clk);
 		clk_prepare_enable(mehci->ahb_clk);
+		if (!IS_ERR(mehci->inactivity_clk))
+			clk_prepare_enable(mehci->inactivity_clk);
 	}
 }
 
@@ -794,6 +799,8 @@
 	clk_disable_unprepare(mehci->phy_clk);
 	clk_disable_unprepare(mehci->cal_clk);
 	clk_disable_unprepare(mehci->ahb_clk);
+	if (!IS_ERR(mehci->inactivity_clk))
+		clk_disable_unprepare(mehci->inactivity_clk);
 
 	none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
 	max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
@@ -876,6 +883,8 @@
 	clk_prepare_enable(mehci->phy_clk);
 	clk_prepare_enable(mehci->cal_clk);
 	clk_prepare_enable(mehci->ahb_clk);
+	if (!IS_ERR(mehci->inactivity_clk))
+		clk_prepare_enable(mehci->inactivity_clk);
 
 	temp = readl_relaxed(USB_USBCMD);
 	temp &= ~ASYNC_INTR_CTRL;
@@ -1507,10 +1516,21 @@
 		goto put_cal_clk;
 	}
 
+	/*
+	 * Inactivity_clk is required for hsic bam inactivity timer.
+	 * This clock is not compulsory and is defined in clock lookup
+	 * only for targets that need to use the inactivity timer feature.
+	 */
+	mehci->inactivity_clk = clk_get(mehci->dev, "inactivity_clk");
+	if (IS_ERR(mehci->inactivity_clk))
+		dev_dbg(mehci->dev, "failed to get inactivity_clk\n");
+
 	clk_prepare_enable(mehci->core_clk);
 	clk_prepare_enable(mehci->phy_clk);
 	clk_prepare_enable(mehci->cal_clk);
 	clk_prepare_enable(mehci->ahb_clk);
+	if (!IS_ERR(mehci->inactivity_clk))
+		clk_prepare_enable(mehci->inactivity_clk);
 
 	return 0;
 
@@ -1520,7 +1540,11 @@
 		clk_disable_unprepare(mehci->phy_clk);
 		clk_disable_unprepare(mehci->cal_clk);
 		clk_disable_unprepare(mehci->ahb_clk);
+		if (!IS_ERR(mehci->inactivity_clk))
+			clk_disable_unprepare(mehci->inactivity_clk);
 	}
+	if (!IS_ERR(mehci->inactivity_clk))
+		clk_put(mehci->inactivity_clk);
 	clk_put(mehci->ahb_clk);
 put_cal_clk:
 	clk_put(mehci->cal_clk);
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index c2b35c8..c219725 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -368,6 +368,9 @@
 	/* DTS value associated with the buffer */
 	__u64 dts;
 
+	/* STC value associated with the buffer in 27MHz */
+	__u64 stc;
+
 	/*
 	 * Number of TS packets with Transport Error Indicator (TEI) set
 	 * in the TS packet header since last reported event
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index bce6af3..b71aa30 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -207,6 +207,7 @@
 	uint8_t settle_cnt;
 	uint16_t lane_mask;
 	uint8_t combo_mode;
+	uint8_t csid_core;
 };
 
 struct msm_camera_csi2_params {
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index afd5a42..b4b3bfc 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1396,6 +1396,7 @@
 	uint8_t settle_cnt;
 	uint16_t lane_mask;
 	uint8_t combo_mode;
+	uint8_t csid_core;
 };
 
 struct msm_camera_csi2_params {
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 6fb1a65..bf6b23b 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -168,12 +168,6 @@
 	enum msm_vfe_frame_skip_pattern skip_pattern;
 };
 
-enum msm_vfe_stats_pipeline_policy {
-	STATS_COMP_ALL,
-	STATS_COMP_NONE,
-	MAX_STATS_POLICY,
-};
-
 enum msm_isp_stats_type {
 	MSM_ISP_STATS_AEC,   /* legacy based AEC */
 	MSM_ISP_STATS_AF,    /* legacy based AF */
@@ -193,11 +187,11 @@
 	uint32_t session_id;
 	uint32_t stream_id;
 	enum msm_isp_stats_type stats_type;
+	uint32_t composite_flag;
 	uint32_t framedrop_pattern;
 	uint32_t irq_subsample_pattern;
 	uint32_t buffer_offset;
 	uint32_t stream_handle;
-	uint8_t comp_flag;
 };
 
 struct msm_vfe_stats_stream_release_cmd {
@@ -209,12 +203,6 @@
 	uint8_t enable;
 };
 
-struct msm_vfe_stats_comp_policy_cfg {
-	enum msm_vfe_stats_pipeline_policy stats_pipeline_policy;
-	uint32_t comp_framedrop_pattern;
-	uint32_t comp_irq_subsample_pattern;
-};
-
 enum msm_vfe_reg_cfg_type {
 	VFE_WRITE,
 	VFE_WRITE_MB,
@@ -319,7 +307,7 @@
 #define ISP_EVENT_EOF             (ISP_EVENT_BASE + ISP_EOF)
 #define ISP_EVENT_BUF_DIVERT      (ISP_BUF_EVENT_BASE)
 #define ISP_EVENT_STATS_NOTIFY    (ISP_STATS_EVENT_BASE)
-
+#define ISP_EVENT_COMP_STATS_NOTIFY (ISP_EVENT_STATS_NOTIFY + MSM_ISP_STATS_MAX)
 /* The msm_v4l2_event_data structure should match the
  * v4l2_event.u.data field.
  * should not exceed 64 bytes */
@@ -412,10 +400,6 @@
 	_IOWR('V', BASE_VIDIOC_PRIVATE+11, \
 	struct msm_vfe_stats_stream_release_cmd)
 
-#define VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY \
-	_IOWR('V', BASE_VIDIOC_PRIVATE+12,   \
-	      struct msm_vfe_stats_comp_policy_cfg)
-
 #define VIDIOC_MSM_ISP_UPDATE_STREAM \
 	_IOWR('V', BASE_VIDIOC_PRIVATE+13, struct msm_vfe_axi_stream_update_cmd)