Merge "ARM: dts: msm: Add support for new Qseecom_ta ion heap for sdm845"
diff --git a/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt b/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
index ccefc98..9f40a09 100644
--- a/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
@@ -1,4 +1,4 @@
-Qualcomm RPM Regulators
+Qualcomm Technologies, Inc. RPM Regulators
 
 rpm-regulator-smd is a regulator driver which supports regulators inside of
 PMICs which are controlled by the RPM processor.  Communication with the RPM
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index 6716785..6405371 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -38,7 +38,8 @@
 
 Required properties:
  - compatible: Should be "qcom,usb-ssphy-qmp", "qcom,usb-ssphy-qmp-v1" or
-   "qcom,usb-ssphy-qmp-v2" or "qcom,usb-ssphy-qmp-dp-combo"
+   "qcom,usb-ssphy-qmp-v2" or "qcom,usb-ssphy-qmp-usb3-or-dp" or
+   "qcom,usb-ssphy-qmp-dp-combo"
  - reg: Address and length of the register set for the device
    Required regs are:
    "qmp_phy_base" : QMP PHY Base register set.
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi
index 7819d26..e6dc45a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi
@@ -23,6 +23,9 @@
 		reg-names = "mc_virt-base", "mem_noc-base",
 			"system_noc-base", "ipa_virt-base";
 
+		mbox-names = "apps_rsc";
+		mboxes = <&apps_rsc 0>;
+
 		/*RSCs*/
 		rsc_apps: rsc-apps {
 			cell-id = <MSM_BUS_RSC_APPS>;
@@ -360,7 +363,7 @@
 			label = "mas-qhm-qpic";
 			qcom,buswidth = <4>;
 			qcom,agg-ports = <1>;
-			qcom,connections = <&slv_qhs_aoss &slv_qns_aggre_noc>;
+			qcom,connections = <&slv_qns_aggre_noc>;
 			qcom,bus-dev = <&fab_system_noc>;
 			qcom,bcms = <&bcm_pn3>;
 		};
@@ -451,7 +454,7 @@
 			qcom,buswidth = <8>;
 			qcom,agg-ports = <1>;
 			qcom,qport = <1>;
-			qcom,connections = <&slv_qhs_aoss &slv_qns_aggre_noc>;
+			qcom,connections = <&slv_qns_aggre_noc>;
 			qcom,bus-dev = <&fab_system_noc>;
 			qcom,bcms = <&bcm_ce>, <&bcm_pn5>;
 			qcom,ap-owned;
@@ -538,7 +541,7 @@
 			qcom,buswidth = <8>;
 			qcom,agg-ports = <1>;
 			qcom,qport = <8>;
-			qcom,connections = <&slv_qhs_aoss &slv_qns_aggre_noc>;
+			qcom,connections = <&slv_qns_aggre_noc>;
 			qcom,bus-dev = <&fab_system_noc>;
 			qcom,bcms = <&bcm_pn1>;
 			qcom,ap-owned;
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
index 9947594..e62c4a3 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
@@ -64,6 +64,13 @@
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
+
+		cx_cdev: regulator-cdev {
+			compatible = "qcom,rpmh-reg-cdev";
+			mboxes = <&qmp_aop 0>;
+			qcom,reg-resource-name = "cx";
+			#cooling-cells = <2>;
+		};
 	};
 
 	rpmh-regulator-ldoa1 {
@@ -99,7 +106,6 @@
 			 regulator-max-microvolt = <1128000>;
 			 qcom,init-voltage = <1128000>;
 			 qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
-			 regulator-always-on;
 		 };
 	};
 
@@ -168,9 +174,9 @@
 		pmxpoorwills_l7: regualtor-pmxpoorwills-l7 {
 			regulator-name = "pmxpoorwills_l7";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			regulator-min-microvolt = <2952000>;
+			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2952000>;
-			qcom,init-voltage = <2952000>;
+			qcom,init-voltage = <1800000>;
 			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
 		};
 	};
@@ -186,9 +192,9 @@
 		pmxpoorwills_l8: regualtor-pmxpoorwills-l8 {
 			regulator-name = "pmxpoorwills_l8";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			regulator-min-microvolt = <800000>;
-			regulator-max-microvolt = <800000>;
-			qcom,init-voltage = <800000>;
+			regulator-min-microvolt = <480000>;
+			regulator-max-microvolt = <900000>;
+			qcom,init-voltage = <480000>;
 			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
 		};
 	};
@@ -211,6 +217,14 @@
 			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 		};
+
+		mx_cdev: mx-cdev-lvl {
+			compatible = "qcom,regulator-cooling-device";
+			regulator-cdev-supply = <&pmxpoorwills_l9_level>;
+			regulator-levels = <RPMH_REGULATOR_LEVEL_NOM
+					RPMH_REGULATOR_LEVEL_OFF>;
+			#cooling-cells = <2>;
+		};
 	};
 
 	rpmh-regulator-ldoa10 {
@@ -242,9 +256,9 @@
 		pmxpoorwills_l11: regualtor-pmxpoorwills-l11 {
 			  regulator-name = "pmxpoorwills_l11";
 			  qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			  regulator-min-microvolt = <1808000>;
-			  regulator-max-microvolt = <1808000>;
-			  qcom,init-voltage = <1808000>;
+			  regulator-min-microvolt = <1704000>;
+			  regulator-max-microvolt = <3000000>;
+			  qcom,init-voltage = <1704000>;
 			  qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
 		  };
 	};
@@ -278,9 +292,9 @@
 		pmxpoorwills_l13: regualtor-pmxpoorwills-l13 {
 			  regulator-name = "pmxpoorwills_l13";
 			  qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			  regulator-min-microvolt = <1808000>;
-			  regulator-max-microvolt = <1808000>;
-			  qcom,init-voltage = <1808000>;
+			  regulator-min-microvolt = <1704000>;
+			  regulator-max-microvolt = <3000000>;
+			  qcom,init-voltage = <1704000>;
 			  qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
 		  };
 	};
@@ -296,9 +310,9 @@
 		pmxpoorwills_l14: regualtor-pmxpoorwills-l14 {
 			  regulator-name = "pmxpoorwills_l14";
 			  qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			  regulator-min-microvolt = <620000>;
-			  regulator-max-microvolt = <620000>;
-			  qcom,init-voltage = <620000>;
+			  regulator-min-microvolt = <600000>;
+			  regulator-max-microvolt = <800000>;
+			  qcom,init-voltage = <600000>;
 			  qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
 		  };
 	};
@@ -314,11 +328,10 @@
 		pmxpoorwills_l16: regualtor-pmxpoorwills-l16 {
 			  regulator-name = "pmxpoorwills_l16";
 			  qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			  regulator-min-microvolt = <752000>;
-			  regulator-max-microvolt = <752000>;
-			  qcom,init-voltage = <752000>;
+			  regulator-min-microvolt = <304000>;
+			  regulator-max-microvolt = <880000>;
+			  qcom,init-voltage = <304000>;
 			  qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
-			  regulator-always-on;
 		  };
 	};
 
@@ -332,4 +345,18 @@
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
 		};
 	};
+
+	/* Stub regulators */
+
+	/*
+	 * RPMh does not provide support for PMXPOORWILLS L6 because it is
+	 * always on at 1.8 V.  Therefore, use a fixed regulator for L6.
+	 */
+	pmxpoorwills_l6: regulator-pmxpoorwills-l6 {
+		compatible = "regulator-fixed";
+		regulator-name = "pmxpoorwills_l6";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts
index a60538d..b73d3aa 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts
@@ -43,6 +43,8 @@
 	/delete-node/ rpmh-regulator-ldoa14;
 	/delete-node/ rpmh-regulator-ldoa16;
 	/delete-node/ rpmh-regulator-rgmii;
+
+	/delete-node/ thermal-zones;
 };
 
 #include "sdxpoorwills-stub-regulator.dtsi"
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi
index 5a4810a..65467f9 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi
@@ -163,6 +163,14 @@
 				trip = <&aoss_trip>;
 				cooling-device = <&adsp_vdd 0 0>;
 			};
+			cx_vdd_cdev {
+				trip = <&aoss_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&aoss_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
 		};
 	};
 
@@ -188,6 +196,14 @@
 				trip = <&mdm_q6_trip>;
 				cooling-device = <&adsp_vdd 0 0>;
 			};
+			cx_vdd_cdev {
+				trip = <&mdm_q6_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_q6_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
 		};
 	};
 
@@ -213,6 +229,14 @@
 				trip = <&ddrss_trip>;
 				cooling-device = <&adsp_vdd 0 0>;
 			};
+			cx_vdd_cdev {
+				trip = <&ddrss_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&ddrss_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
 		};
 	};
 
@@ -238,6 +262,14 @@
 				trip = <&cpu_trip>;
 				cooling-device = <&adsp_vdd 0 0>;
 			};
+			cx_vdd_cdev {
+				trip = <&cpu_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&cpu_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
 		};
 	};
 
@@ -263,6 +295,14 @@
 				trip = <&mdm_trip>;
 				cooling-device = <&adsp_vdd 0 0>;
 			};
+			cx_vdd_cdev {
+				trip = <&mdm_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
 		};
 	};
 
@@ -274,8 +314,8 @@
 		tracks-low;
 		trips {
 			mdm_vpe_trip: mdm-vpe-trip {
-				temperature = <125000>;
-				hysteresis = <1000>;
+				temperature = <5000>;
+				hysteresis = <5000>;
 				type = "passive";
 			};
 		};
@@ -288,6 +328,49 @@
 				trip = <&mdm_vpe_trip>;
 				cooling-device = <&adsp_vdd 0 0>;
 			};
+			cx_vdd_cdev {
+				trip = <&mdm_vpe_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_vpe_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
 		};
 	};
+
+	xo-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmxpoorwills_vadc 0x4c>;
+		thermal-governor = "user_space";
+	};
+
+	pa-therm1-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmxpoorwills_vadc 0x4d>;
+		thermal-governor = "user_space";
+	};
+
+	pa-therm2-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmxpoorwills_vadc 0x4e>;
+		thermal-governor = "user_space";
+	};
+
+	mdm-case-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmxpoorwills_vadc 0x4f>;
+		thermal-governor = "user_space";
+	};
+
+	ambient-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmxpoorwills_vadc 0x52>;
+		thermal-governor = "user_space";
+	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index ce38838..b6393a91 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -306,10 +306,10 @@
 		};
 };
 
-	restart@4ab000 {
+	restart@c264000 {
 		compatible = "qcom,pshold";
-		reg = <0x4ab000 0x4>,
-			<0x193d100 0x4>;
+		reg = <0x0c264000 0x4>,
+			<0x01fd3000 0x4>;
 		reg-names = "pshold-base", "tcsr-boot-misc-detect";
 	};
 
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 944fe67..fd1cac3 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -358,6 +358,8 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index c744f9e..c126ccd 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -370,6 +370,8 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index 456ff5e..e015eff 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -228,6 +228,7 @@
 CONFIG_CPU_THERMAL=y
 CONFIG_THERMAL_QPNP=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
 CONFIG_REGULATOR_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index f2b20b0..d0568aa 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -221,6 +221,7 @@
 CONFIG_CPU_THERMAL=y
 CONFIG_THERMAL_QPNP=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
 CONFIG_REGULATOR_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
@@ -312,6 +313,8 @@
 CONFIG_MSM_QMP=y
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
 CONFIG_MSM_SMEM=y
 CONFIG_MSM_GLINK=y
 CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
@@ -328,6 +331,7 @@
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_MSM_PM=y
 CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_IIO=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
index 7705d01..1990b65 100644
--- a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
@@ -17,42 +17,42 @@
 	qcom,fastchg-current-ma = <3450>;
 	qcom,batt-id-kohm = <60>;
 	qcom,battery-beta = <3435>;
-	qcom,battery-type = "ascent_3450mah_averaged_masterslave_jul11th2017";
-	qcom,checksum = <0x7C33>;
+	qcom,battery-type = "ascent_3450mah_averaged_masterslave_oct30th2017";
+	qcom,checksum = <0xAAE2>;
 	qcom,gui-version = "PMI8998GUI - 2.0.0.58";
 	qcom,fg-profile-data = [
 		8F 1F 94 05
 		73 0A 4A 06
 		27 1D 21 EA
-		16 0A 3B 0C
+		16 0A 3A 0C
 		07 18 97 22
 		A5 3C EC 4A
 		5C 00 00 00
 		10 00 00 00
-		00 00 92 BC
-		CD BD 02 B4
+		00 00 43 C5
+		92 BC 89 BB
 		11 00 08 00
 		69 DA AD 07
 		4B FD 19 FA
-		1D 0C B0 0C
+		7E 01 49 13
 		EB F3 78 3B
 		24 06 09 20
 		27 00 14 00
 		7E 1F F2 05
-		19 0A 55 FD
-		6C 1D C6 ED
+		19 0A AB 06
+		6C 1D B9 07
 		1A 12 FF 1D
 		6F 18 EB 22
 		B9 45 6F 52
 		55 00 00 00
 		0E 00 00 00
-		00 00 A1 D5
-		34 BA A0 CA
+		00 00 33 CC
+		72 CA B3 C4
 		0F 00 00 00
 		93 00 AD 07
 		8D FD F6 00
-		BA 0D 5C 04
-		B3 FC F4 1B
+		6F E3 44 0B
+		AB FC F9 1B
 		C3 33 CC FF
 		07 10 00 00
 		A4 0D 99 45
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi
index ae22a36..ab088b8 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi
@@ -322,3 +322,19 @@
 		dma-coherent;
 	};
 };
+
+&apps_smmu {
+	qcom,actlr =	<0x0880 0x8 0x103>,
+			<0x0881 0x8 0x103>,
+			<0x0c80 0x8 0x103>,
+			<0x0c81 0x8 0x103>,
+			<0x1090 0x0 0x103>,
+			<0x1091 0x0 0x103>,
+			<0x10a0 0x8 0x103>,
+			<0x10b0 0x0 0x103>,
+			<0x10a1 0x8 0x103>,
+			<0x10a3 0x8 0x103>,
+			<0x10a4 0x8 0x103>,
+			<0x10b4 0x0 0x103>,
+			<0x10a5 0x8 0x103>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index a9ca87c..0a2b814 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -257,6 +257,229 @@
 		qcom,pipe-attr-ee;
 	};
 
+	thermal_zones: thermal-zones {
+		mdm-core-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "user_space";
+			thermal-sensors = <&tsens0 1>;
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		qdsp-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "user_space";
+			thermal-sensors = <&tsens0 2>;
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		camera-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "user_space";
+			thermal-sensors = <&tsens0 3>;
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc1_cpu0-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 4>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc1_cpu1-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 5>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc1_cpu2-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 6>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc1_cpu3-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 7>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc1_l2-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 8>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc0_cpu0-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 9>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc0_cpu1-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 10>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc0_cpu2-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 11>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc0_cpu3-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 12>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		apc0_l2-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 13>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		gpu0-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 14>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+
+		gpu1-usr {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 15>;
+			thermal-governor = "user_space";
+			trips {
+				active-config0 {
+					temperature = <125000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+			};
+		};
+	};
+
+	tsens0: tsens@4a8000 {
+		compatible = "qcom,msm8953-tsens";
+		reg = <0x4a8000 0x1000>,
+			<0x4a9000 0x1000>;
+		reg-names = "tsens_srot_physical",
+					"tsens_tm_physical";
+		interrupts = <0 184 0>, <0 314 0>;
+		interrupt-names = "tsens-upper-lower", "tsens-critical";
+		#thermal-sensor-cells = <1>;
+	};
+
 	blsp1_uart0: serial@78af000 {
 		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 		reg = <0x78af000 0x200>;
diff --git a/arch/arm64/boot/dts/qcom/pm8953.dtsi b/arch/arm64/boot/dts/qcom/pm8953.dtsi
index 60162e3..0ddb9f5 100644
--- a/arch/arm64/boot/dts/qcom/pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8953.dtsi
@@ -82,6 +82,12 @@
 			mpp@a100 {
 				reg = <0xa100 0x100>;
 				qcom,pin-num = <2>;
+				/* MPP2 - PA_THERM config */
+				qcom,mode = <4>; /* AIN input */
+				qcom,invert = <1>; /* Enable MPP */
+				qcom,ain-route = <1>; /* AMUX 6 */
+				qcom,master-en = <1>;
+				qcom,src-sel = <0>; /* Function constant */
 			};
 
 			mpp@a200 {
@@ -93,6 +99,12 @@
 			mpp@a300 {
 				reg = <0xa300 0x100>;
 				qcom,pin-num = <4>;
+				/* MPP4 - CASE_THERM config */
+				qcom,mode = <4>; /* AIN input */
+				qcom,invert = <1>; /* Enable MPP */
+				qcom,ain-route = <3>; /* AMUX 8 */
+				qcom,master-en = <1>;
+				qcom,src-sel = <0>; /* Function constant */
 			};
 		};
 
@@ -165,6 +177,28 @@
 			qcom,adc-vdd-reference = <1800>;
 			qcom,vadc-poll-eoc;
 
+			chan@5 {
+				label = "vcoin";
+				reg = <5>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <1>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@7 {
+				label = "vph_pwr";
+				reg = <7>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <1>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
 			chan@8 {
 				label = "die_temp";
 				reg = <8>;
@@ -208,6 +242,63 @@
 				qcom,hw-settle-time = <0>;
 				qcom,fast-avg-setup = <0>;
 			};
+
+			chan@36 {
+				label = "pa_therm0";
+				reg = <0x36>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <2>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@11 {
+				label = "pa_therm1";
+				reg = <0x11>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <2>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+
+			chan@32 {
+				label = "xo_therm";
+				reg = <0x32>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <4>;
+				qcom,hw-settle-time = <2>;
+				qcom,fast-avg-setup = <0>;
+				qcom,vadc-thermal-node;
+			};
+
+			chan@3c {
+				label = "xo_therm_buf";
+				reg = <0x3c>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <4>;
+				qcom,hw-settle-time = <2>;
+				qcom,fast-avg-setup = <0>;
+				qcom,vadc-thermal-node;
+			};
+			chan@13 {
+				label = "case_therm";
+				reg = <0x13>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <2>;
+				qcom,fast-avg-setup = <0>;
+			};
 		};
 
 		pm8953_adc_tm: vadc@3400 {
@@ -224,7 +315,6 @@
 			qcom,adc-bit-resolution = <15>;
 			qcom,adc-vdd-reference = <1800>;
 			qcom,adc_tm-vadc = <&pm8953_vadc>;
-
 		};
 
 		pm8953_rtc: qcom,pm8953_rtc {
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index dc3ffda..89499f8 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -248,7 +248,7 @@
 			pm8998_trip2: pm8998-trip2 {
 				temperature = <145000>;
 				hysteresis = <0>;
-				type = "critical";
+				type = "passive";
 			};
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 5b48c14..2f4b00e 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -103,6 +103,7 @@
 			qcom,thermal-mitigation
 					= <3000000 1500000 1000000 500000>;
 			qcom,auto-recharge-soc;
+			qcom,suspend-input-on-debug-batt;
 
 			qcom,chgr@1000 {
 				reg = <0x1000 0x100>;
@@ -731,7 +732,7 @@
 
 		trips {
 			ibat_high: low-ibat {
-				temperature = <4200>;
+				temperature = <5000>;
 				hysteresis = <200>;
 				type = "passive";
 			};
@@ -745,7 +746,7 @@
 
 		trips {
 			ibat_vhigh: ibat_vhigh {
-				temperature = <4300>;
+				temperature = <6000>;
 				hysteresis = <100>;
 				type = "passive";
 			};
@@ -760,7 +761,7 @@
 
 		trips {
 			low_vbat: low-vbat {
-				temperature = <3300>;
+				temperature = <3200>;
 				hysteresis = <100>;
 				type = "passive";
 			};
@@ -801,7 +802,7 @@
 
 		trips {
 			low-vbat {
-				temperature = <3100>;
+				temperature = <2800>;
 				hysteresis = <0>;
 				type = "passive";
 			};
@@ -816,7 +817,7 @@
 
 		trips {
 			low-vbat {
-				temperature = <2900>;
+				temperature = <2600>;
 				hysteresis = <0>;
 				type = "passive";
 			};
@@ -883,7 +884,7 @@
 			 pmi8998_trip2: pmi8998-trip2 {
 				temperature = <145000>;
 				hysteresis = <0>;
-				type = "critical";
+				type = "passive";
 			};
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
index b46cbfd..025d9a2 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
@@ -10,6 +10,10 @@
  * GNU General Public License for more details.
  */
 
+#include "pm8005.dtsi"
+#include "sdm670-pmic-overlay.dtsi"
+#include "qcs605-pm660-pm8005-regulator.dtsi"
+
 / {
 	cpus {
 		/delete-node/ cpu@200;
@@ -111,3 +115,91 @@
 		};
 	};
 };
+
+&spmi_bus {
+	/delete-node/ qcom,pm660l@2;
+	/delete-node/ qcom,pm660l@3;
+};
+
+&thermal_zones {
+	pm660l_tz {
+		/delete-property/ thermal-sensors;
+	};
+};
+
+&soc {
+	qcom,turing@8300000 {
+		/delete-property/ vdd_cx-supply;
+	};
+
+	qcom,lpass@62400000 {
+		/delete-property/ vdd_cx-supply;
+	};
+};
+
+&clock_cpucc {
+	/delete-property/ vdd_l3_mx_ao-supply;
+	/delete-property/ vdd_pwrcl_mx_ao-supply;
+};
+
+&clock_gcc {
+	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_cx_ao-supply;
+};
+
+&clock_videocc {
+	/delete-property/ vdd_cx-supply;
+};
+
+&clock_camcc {
+	/delete-property/ vdd_mx-supply;
+	/delete-property/ vdd_cx-supply;
+};
+
+&clock_dispcc {
+	/delete-property/ vdd_cx-supply;
+};
+
+&clock_gpucc {
+	/delete-property/ vdd_mx-supply;
+	/delete-property/ vdd_cx-supply;
+};
+
+&pil_modem {
+	/delete-property/ vdd_mx-supply;
+	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_mss-supply;
+};
+
+&clock_gfx {
+	/delete-property/ vdd_gfx-supply;
+};
+
+&gpu_gx_gdsc {
+	/delete-property/ parent-supply;
+};
+
+&mdss_dsi_phy0 {
+	/delete-property/ vdda-0p9-supply;
+};
+
+&mdss_dsi_phy1 {
+	/delete-property/ vdda-0p9-supply;
+};
+
+&sde_dp {
+	/delete-property/ vdda-0p9-supply;
+};
+
+&qusb_phy0 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vdda33-supply;
+};
+
+&usb_qmp_dp_phy {
+	/delete-property/ vdd-supply;
+};
+
+&pm660_pdphy {
+	/delete-property/ vdd-pdphy-supply;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
new file mode 100644
index 0000000..a881ec4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
@@ -0,0 +1,474 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR  PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+&soc {
+	/* Delete all regulators */
+	/delete-node/ rpmh-regulator-smpa4;
+	/delete-node/ rpmh-regulator-modemlvl;
+	/delete-node/ rpmh-regulator-smpa6;
+	/delete-node/ rpmh-regulator-mxlvl;
+	/delete-node/ rpmh-regulator-gfxlvl;
+	/delete-node/ rpmh-regulator-cxlvl;
+	/delete-node/ rpmh-regulator-ldoa1;
+	/delete-node/ rpmh-regulator-ldoa2;
+	/delete-node/ rpmh-regulator-ldoa3;
+	/delete-node/ rpmh-regulator-ldoa5;
+	/delete-node/ rpmh-regulator-ldoa6;
+	/delete-node/ rpmh-regulator-ldoa7;
+	/delete-node/ rpmh-regulator-ldoa8;
+	/delete-node/ rpmh-regulator-ldoa9;
+	/delete-node/ rpmh-regulator-ldoa10;
+	/delete-node/ rpmh-regulator-ldoa11;
+	/delete-node/ rpmh-regulator-ldoa12;
+	/delete-node/ rpmh-regulator-ldoa13;
+	/delete-node/ rpmh-regulator-ldoa14;
+	/delete-node/ rpmh-regulator-ldoa15;
+	/delete-node/ rpmh-regulator-ldoa16;
+	/delete-node/ rpmh-regulator-ldoa17;
+	/delete-node/ rpmh-regulator-ldoa19;
+	/delete-node/ rpmh-regulator-ldob1;
+	/delete-node/ rpmh-regulator-ldob2;
+	/delete-node/ rpmh-regulator-ldob3;
+	/delete-node/ rpmh-regulator-ldob4;
+	/delete-node/ rpmh-regulator-ldob5;
+	/delete-node/ rpmh-regulator-ldob6;
+	/delete-node/ rpmh-regulator-ldob7;
+	/delete-node/ rpmh-regulator-ldob8;
+	/delete-node/ rpmh-regulator-lcxlvl;
+	/delete-node/ rpmh-regulator-lmxlvl;
+	/delete-node/ rpmh-regulator-bobb1;
+
+	/* RPMh regulators */
+
+	/* pm660 S2 - VDD_MX supply */
+	rpmh-regulator-mxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "mx.lvl";
+		pm660_s2_level: regulator-pm660-s2 {
+			regulator-name = "pm660_s2_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+
+		pm660_s2_level_ao: regulator-pm660-s2-level-ao {
+			regulator-name = "pm660_s2_level_ao";
+			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+
+		mx_cdev: mx-cdev-lvl {
+			compatible = "qcom,regulator-cooling-device";
+			regulator-cdev-supply = <&pm660_s2_level>;
+			regulator-levels = <RPMH_REGULATOR_LEVEL_NOM
+					RPMH_REGULATOR_LEVEL_OFF>;
+			#cooling-cells = <2>;
+		};
+	};
+
+	rpmh-regulator-smpa4 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "smpa4";
+		pm660_s4: regulator-pm660-s4 {
+			regulator-name = "pm660_s4";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1640000>;
+			regulator-max-microvolt = <2040000>;
+			qcom,init-voltage = <1640000>;
+		};
+	};
+
+	/* pm8005 S1 + S4 - VDD_CX supply */
+	rpmh-regulator-cxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "cx.lvl";
+		pm8005_s1_level-parent-supply = <&pm660_s2_level>;
+		pm8005_s1_level_ao-parent-supply = <&pm660_s2_level_ao>;
+		pm8005_s1_level: regulator-pm8005-s1-level {
+			regulator-name = "pm8005_s1_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+			qcom,min-dropout-voltage-level = <(-1)>;
+		};
+
+		pm8005_s1_level_ao: regulator-pm8005-s1-level-ao {
+			regulator-name = "pm8005_s1_level_ao";
+			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+			qcom,min-dropout-voltage-level = <(-1)>;
+		};
+
+		cx_cdev: regulator-cdev {
+			compatible = "qcom,rpmh-reg-cdev";
+			mboxes = <&qmp_aop 0>;
+			qcom,reg-resource-name = "cx";
+			#cooling-cells = <2>;
+		};
+	};
+
+	rpmh-regulator-smpc2 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "smpc2";
+		pm8005_s2: regulator-pm8005-s2 {
+			regulator-name = "pm8005_s2";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1000000>;
+		};
+	};
+
+	/* pm8005 S3 - VDD_GFX supply */
+	rpmh-regulator-gfxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "gfx.lvl";
+		pm8005_s3_level: regulator-pm8005-s3 {
+			regulator-name = "pm8005_s3_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+			regulator-max-microvolt
+				= <RPMH_REGULATOR_LEVEL_MAX>;
+			qcom,init-voltage-level
+				= <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+		};
+	};
+
+	rpmh-regulator-ldoa1 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa1";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l1: regulator-pm660-l1 {
+			regulator-name = "pm660_l1";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <800000>;
+			regulator-max-microvolt = <800000>;
+			qcom,init-voltage = <800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa2 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa2";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l2: regulator-pm660-l2 {
+			regulator-name = "pm660_l2";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1144000>;
+			regulator-max-microvolt = <1256000>;
+			qcom,init-voltage = <1144000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa3 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa3";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l3: regulator-pm660-l3 {
+			regulator-name = "pm660_l3";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1352000>;
+			qcom,init-voltage = <1200000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa5 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa5";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l5: regulator-pm660-l5 {
+			regulator-name = "pm660_l5";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1304000>;
+			qcom,init-voltage = <1200000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa6 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa6";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l6: regulator-pm660-l6 {
+			regulator-name = "pm660_l6";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <880000>;
+			regulator-max-microvolt = <880000>;
+			qcom,init-voltage = <880000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	/* pm660 L7 = VDD_LPI_CX supply */
+	rpmh-regulator-lcxlvl {
+		compatible = "qcom,rpmh-arc-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "lcx.lvl";
+		pm660_l7_level: regulator-pm660-l7-level {
+			regulator-name = "pm660_l7_level";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
+		};
+	};
+
+	rpmh-regulator-ldoa8 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa8";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l8: regulator-pm660-l8 {
+			regulator-name = "pm660_l8";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1696000>;
+			regulator-max-microvolt = <1952000>;
+			qcom,init-voltage = <1696000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa9 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa9";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l9: regulator-pm660-l9 {
+			regulator-name = "pm660_l9";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1616000>;
+			regulator-max-microvolt = <1984000>;
+			qcom,init-voltage = <1616000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa10 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa10";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l10: regulator-pm660-l10 {
+			regulator-name = "pm660_l10";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1696000>;
+			regulator-max-microvolt = <1952000>;
+			qcom,init-voltage = <1696000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa11 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa11";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l11: regulator-pm660-l11 {
+			regulator-name = "pm660_l11";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1904000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa12 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa12";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l12: regulator-pm660-l12 {
+			regulator-name = "pm660_l12";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1616000>;
+			regulator-max-microvolt = <1984000>;
+			qcom,init-voltage = <1616000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa13 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa13";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l13: regulator-pm660-l13 {
+			regulator-name = "pm660_l13";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1696000>;
+			regulator-max-microvolt = <1904000>;
+			qcom,init-voltage = <1696000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa14 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa14";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l14: regulator-pm660-l14 {
+			regulator-name = "pm660_l14";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1696000>;
+			regulator-max-microvolt = <1904000>;
+			qcom,init-voltage = <1696000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa15 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa15";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l15: regulator-pm660-l15 {
+			regulator-name = "pm660_l15";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2896000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <2896000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa16 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa16";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l16: regulator-pm660-l16 {
+		regulator-name = "pm660_l16";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2896000>;
+			regulator-max-microvolt = <3104000>;
+			qcom,init-voltage = <2896000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa17 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa17";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l17: regulator-pm660-l17 {
+			regulator-name = "pm660_l17";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2920000>;
+			regulator-max-microvolt = <3232000>;
+			qcom,init-voltage = <2920000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa18 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa18";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l18: regulator-pm660-l18 {
+			regulator-name = "pm660_l18";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+
+	rpmh-regulator-ldoa19 {
+		compatible = "qcom,rpmh-vrm-regulator";
+		mboxes = <&apps_rsc 0>;
+		qcom,resource-name = "ldoa19";
+		qcom,supported-modes =
+			<RPMH_REGULATOR_MODE_LDO_LPM
+			 RPMH_REGULATOR_MODE_LDO_HPM>;
+		qcom,mode-threshold-currents = <0 1>;
+		pm660_l19: regulator-pm660-l19 {
+			regulator-name = "pm660_l19";
+			qcom,set = <RPMH_REGULATOR_SET_ALL>;
+			regulator-min-microvolt = <2944000>;
+			regulator-max-microvolt = <3304000>;
+			qcom,init-voltage = <2944000>;
+			qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 66493d1..6cf9a82 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -27,3 +27,23 @@
 &ipa_hw {
 	status = "disabled";
 };
+
+&thermal_zones {
+	lmh-dcvs-00 {
+		trips {
+			active-config {
+				temperature = <105000>;
+				hysteresis = <40000>;
+			};
+		};
+	};
+
+	lmh-dcvs-01 {
+		trips {
+			active-config {
+				temperature = <105000>;
+				hysteresis = <40000>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450.dtsi b/arch/arm64/boot/dts/qcom/sdm450.dtsi
index 8087399..b080ff7 100644
--- a/arch/arm64/boot/dts/qcom/sdm450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450.dtsi
@@ -19,3 +19,18 @@
 	qcom,msm-id = <338 0x0>;
 };
 
+&CPU4 {
+	efficiency = <1024>;
+};
+
+&CPU5 {
+	efficiency = <1024>;
+};
+
+&CPU6 {
+	efficiency = <1024>;
+};
+
+&CPU7 {
+	efficiency = <1024>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
index 6506f98..7ab99a3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
@@ -229,12 +229,13 @@
 		cam_vana-supply = <&cam_rear_avdd_gpio_regulator>;
 		cam_vdig-supply = <&cam_rear_dvdd_gpio_regulator>;
 		cam_clk-supply = <&titan_top_gdsc>;
+		cam_vaf-supply = <&actuator_regulator>;
 		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
-			"cam_clk";
+			"cam_clk", "cam_vaf";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <0 0 0 0>;
-		rgltr-max-voltage = <0 0 0 0>;
-		rgltr-load-current = <0 0 0 0>;
+		rgltr-min-voltage = <1800000 2850000 1200000 0 2800000>;
+		rgltr-max-voltage = <1800000 2850000 1200000 0 2800000>;
+		rgltr-load-current = <0 80000 105000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_active
@@ -266,12 +267,13 @@
 		cam_vana-supply = <&cam_avdd_gpio_regulator>;
 		cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
 		cam_clk-supply = <&titan_top_gdsc>;
-		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
-			"cam_clk";
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk", "cam_vaf";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <0 0 0 0>;
-		rgltr-max-voltage = <0 0 0 0>;
-		rgltr-load-current = <0 0 0 0>;
+		rgltr-min-voltage = <1200000 1800000 2850000 0 2800000>;
+		rgltr-max-voltage = <1200000 1800000 2850000 0 2800000>;
+		rgltr-load-current = <105000 0 80000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk1_active
@@ -303,12 +305,13 @@
 		cam_vana-supply = <&cam_avdd_gpio_regulator>;
 		cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
 		cam_clk-supply = <&titan_top_gdsc>;
+		cam_vaf-supply = <&actuator_regulator>;
 		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
-			"cam_clk";
+			"cam_clk", "cam_vaf";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <0 0 0 0>;
-		rgltr-max-voltage = <0 0 0 0>;
-		rgltr-load-current = <0 0 0 0>;
+		rgltr-min-voltage = <1800000 2850000 1200000 0 2800000>;
+		rgltr-max-voltage = <1800000 2850000 1200000 0 2800000>;
+		rgltr-load-current = <0 80000 105000 0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk2_active
@@ -350,9 +353,9 @@
 		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
 			"cam_clk";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <0 0 0 0>;
-		rgltr-max-voltage = <0 0 0 0>;
-		rgltr-load-current = <0 0 0 0>;
+		rgltr-min-voltage = <1800000 2850000 1200000 0>;
+		rgltr-max-voltage = <1800000 2850000 1200000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_active
@@ -390,12 +393,12 @@
 		cam_vana-supply = <&cam_avdd_gpio_regulator>;
 		cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
 		cam_clk-supply = <&titan_top_gdsc>;
-		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
 			"cam_clk";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <0 0 0 0>;
-		rgltr-max-voltage = <0 0 0 0>;
-		rgltr-load-current = <0 0 0 0>;
+		rgltr-min-voltage = <1200000 1800000 2850000 0>;
+		rgltr-max-voltage = <1200000 1800000 2850000 0>;
+		rgltr-load-current = <105000 0 80000 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk1_active
@@ -435,9 +438,9 @@
 		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
 			"cam_clk";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <0 0 0 0>;
-		rgltr-max-voltage = <0 0 0 0>;
-		rgltr-load-current = <0 0 0 0>;
+		rgltr-min-voltage = <1800000 2850000 1200000 0>;
+		rgltr-max-voltage = <1800000 2850000 1200000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk2_active
diff --git a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
index c64ed2c..c76fbce 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi
@@ -26,7 +26,7 @@
 
 			config {
 				pins = "gpio18";
-				drive-strength = <2>;
+				drive-strength = <4>;
 				output-low;
 			};
 		};
@@ -53,7 +53,7 @@
 
 			config {
 				pins = "gpio19";
-				drive-strength = <2>;
+				drive-strength = <4>;
 				output-low;
 			};
 		};
@@ -80,7 +80,7 @@
 
 			config {
 				pins = "gpio21";
-				drive-strength = <2>;
+				drive-strength = <4>;
 				output-low;
 			};
 		};
@@ -107,7 +107,7 @@
 
 			config {
 				pins = "gpio23", "gpio25";
-				drive-strength = <2>;
+				drive-strength = <4>;
 				output-low;
 			};
 		};
@@ -159,7 +159,7 @@
 
 			config {
 				pins = "gpio22";
-				drive-strength = <2>;
+				drive-strength = <4>;
 			};
 		};
 
@@ -184,7 +184,7 @@
 
 			config {
 				pins = "gpio24";
-				drive-strength = <2>;
+				drive-strength = <4>;
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
index f3c6b00..ea6e1c7 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
@@ -78,6 +78,8 @@
 };
 
 &pm660_charger {
+	qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+				2000000 1500000 1000000 500000>;
 	qcom,battery-data = <&qrd_batterydata>;
 	qcom,sw-jeita-enable;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 0b8ddf3..0163c87 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -464,10 +464,22 @@
 		#size-cells = <2>;
 		ranges;
 
-		removed_regions: removed_regions@85700000 {
+		hyp_region: hyp_region@85700000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x85700000 0 0x3800000>;
+			reg = <0 0x85700000 0 0x600000>;
+		};
+
+		xbl_region: xbl_region@85e00000 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0 0x85e00000 0 0x100000>;
+		};
+
+		removed_region: removed_region@85fc0000 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0 0x85fc0000 0 0x2f40000>;
 		};
 
 		pil_camera_mem: camera_region@8ab00000 {
@@ -2479,6 +2491,7 @@
 		vdd-3.3-ch0-supply = <&pm660_l19>;
 		qcom,vdd-3.3-ch0-config = <3000000 3312000>;
 		qcom,wlan-msa-memory = <0x100000>;
+		qcom,wlan-msa-fixed-region = <&wlan_msa_mem>;
 		qcom,smmu-s1-bypass;
 	};
 
@@ -2787,6 +2800,7 @@
 };
 
 &bps_gdsc {
+	qcom,support-hw-trigger;
 	status = "ok";
 };
 
@@ -2799,10 +2813,12 @@
 };
 
 &ipe_0_gdsc {
+	qcom,support-hw-trigger;
 	status = "ok";
 };
 
 &ipe_1_gdsc {
+	qcom,support-hw-trigger;
 	status = "ok";
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
index f9c6f65..c6622d4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
@@ -62,7 +62,3 @@
 &dsi_sharp_4k_dsc_video_display {
 	qcom,dsi-display-active;
 };
-
-&mdss_mdp {
-	connectors = <&sde_rscc &sde_wb &sde_dp>;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
index cf7ccae..3ce5626 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
@@ -751,38 +751,6 @@
 			qcom,bcms = <&bcm_cn0>;
 		};
 
-		mas_qhm_tic: mas-qhm-tic {
-			cell-id = <MSM_BUS_MASTER_TIC>;
-			label = "mas-qhm-tic";
-			qcom,buswidth = <4>;
-			qcom,agg-ports = <1>;
-			qcom,connections = <&slv_qhs_tlmm_south
-				&slv_qhs_spss_cfg &slv_qhs_camera_cfg
-				 &slv_qhs_sdc4 &slv_qhs_sdc2
-				 &slv_qhs_mnoc_cfg &slv_qhs_ufs_mem_cfg
-				 &slv_qhs_snoc_cfg &slv_qhs_glm
-				 &slv_qhs_pdm &slv_qhs_a2_noc_cfg
-				 &slv_qhs_qdss_cfg &slv_qhs_display_cfg
-				 &slv_qhs_tcsr &slv_qhs_dcc_cfg
-				 &slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc
-				 &slv_qhs_phy_refgen_south
-				 &slv_qhs_pcie_gen3_cfg
-				 &slv_qhs_pcie0_cfg &slv_qhs_gpuss_cfg
-				 &slv_qhs_venus_cfg &slv_qhs_tsif
-				 &slv_qhs_compute_dsp_cfg &slv_qhs_aop
-				 &slv_qhs_qupv3_north &slv_qhs_usb3_0
-				 &slv_srvc_cnoc &slv_qhs_ufs_card_cfg
-				 &slv_qhs_usb3_1 &slv_qhs_ipa
-				 &slv_qhs_cpr_cx &slv_qhs_a1_noc_cfg
-				 &slv_qhs_aoss &slv_qhs_prng
-				 &slv_qhs_vsense_ctrl_cfg &slv_qhs_qupv3_south
-				 &slv_qhs_spdm &slv_qhs_crypto0_cfg
-				 &slv_qhs_pimem_cfg &slv_qhs_tlmm_north
-				 &slv_qhs_clk_ctl &slv_qhs_imem_cfg>;
-			qcom,bus-dev = <&fab_config_noc>;
-			qcom,bcms = <&bcm_cn0>;
-		};
-
 		mas_qnm_snoc: mas-qnm-snoc {
 			cell-id = <MSM_BUS_SNOC_CNOC_MAS>;
 			label = "mas-qnm-snoc";
@@ -814,38 +782,6 @@
 			qcom,bcms = <&bcm_cn0>;
 		};
 
-		mas_xm_qdss_dap: mas-xm-qdss-dap {
-			cell-id = <MSM_BUS_MASTER_QDSS_DAP>;
-			label = "mas-xm-qdss-dap";
-			qcom,buswidth = <8>;
-			qcom,agg-ports = <1>;
-			qcom,connections = <&slv_qhs_tlmm_south
-				 &slv_qhs_spss_cfg &slv_qhs_camera_cfg
-				 &slv_qhs_sdc4 &slv_qhs_sdc2
-				 &slv_qhs_mnoc_cfg &slv_qhs_ufs_mem_cfg
-				 &slv_qhs_snoc_cfg &slv_qhs_glm
-				 &slv_qhs_pdm &slv_qhs_a2_noc_cfg
-				 &slv_qhs_qdss_cfg &slv_qhs_display_cfg
-				 &slv_qhs_tcsr &slv_qhs_dcc_cfg
-				 &slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc
-				 &slv_qhs_phy_refgen_south
-				 &slv_qhs_pcie_gen3_cfg
-				 &slv_qhs_pcie0_cfg &slv_qhs_gpuss_cfg
-				 &slv_qhs_venus_cfg &slv_qhs_tsif
-				 &slv_qhs_compute_dsp_cfg &slv_qhs_aop
-				 &slv_qhs_qupv3_north &slv_qhs_usb3_0
-				 &slv_srvc_cnoc &slv_qhs_ufs_card_cfg
-				 &slv_qhs_usb3_1 &slv_qhs_ipa
-				 &slv_qhs_cpr_cx &slv_qhs_a1_noc_cfg
-				 &slv_qhs_aoss &slv_qhs_prng
-				 &slv_qhs_vsense_ctrl_cfg &slv_qhs_qupv3_south
-				 &slv_qhs_spdm &slv_qhs_crypto0_cfg
-				 &slv_qhs_pimem_cfg &slv_qhs_tlmm_north
-				 &slv_qhs_clk_ctl &slv_qhs_imem_cfg>;
-			qcom,bus-dev = <&fab_config_noc>;
-			qcom,bcms = <&bcm_cn0>;
-		};
-
 		mas_qhm_cnoc: mas-qhm-cnoc {
 			cell-id = <MSM_BUS_MASTER_CNOC_DC_NOC>;
 			label = "mas-qhm-cnoc";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
index 31cfdd6..f31b3a5 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
@@ -97,6 +97,10 @@
 	qcom,cam-res-mgr {
 		compatible = "qcom,cam-res-mgr";
 		status = "ok";
+		shared-gpios = <8>;
+		pinctrl-names = "cam_res_mgr_default", "cam_res_mgr_suspend";
+		pinctrl-0 = <&cam_res_mgr_active>;
+		pinctrl-1 = <&cam_res_mgr_suspend>;
 	};
 
 	actuator_rear: qcom,actuator@0 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
index d7f25977..a3a48af 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -97,6 +97,10 @@
 	qcom,cam-res-mgr {
 		compatible = "qcom,cam-res-mgr";
 		status = "ok";
+		shared-gpios = <8>;
+		pinctrl-names = "cam_res_mgr_default", "cam_res_mgr_suspend";
+		pinctrl-0 = <&cam_res_mgr_active>;
+		pinctrl-1 = <&cam_res_mgr_suspend>;
 	};
 
 	actuator_rear: qcom,actuator@0 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index 244ac1d..191e76d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -2985,12 +2985,12 @@
 		cam_sensor_front_active: cam_sensor_front_active {
 			/* RESET  AVDD_LDO*/
 			mux {
-				pins = "gpio28", "gpio8";
+				pins = "gpio28";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio28", "gpio8";
+				pins = "gpio28";
 				bias-disable; /* No PULL */
 				drive-strength = <2>; /* 2 MA */
 			};
@@ -3014,12 +3014,12 @@
 		cam_sensor_iris_active: cam_sensor_iris_active {
 			/* RESET  AVDD_LDO*/
 			mux {
-				pins = "gpio9", "gpio8";
+				pins = "gpio9";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio9", "gpio8";
+				pins = "gpio9";
 				bias-disable; /* No PULL */
 				drive-strength = <2>; /* 2 MA */
 			};
@@ -3074,12 +3074,12 @@
 		cam_sensor_rear2_active: cam_sensor_rear2_active {
 			/* RESET, STANDBY */
 			mux {
-				pins = "gpio9","gpio8";
+				pins = "gpio9";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio9","gpio8";
+				pins = "gpio9";
 				bias-disable; /* No PULL */
 				drive-strength = <2>; /* 2 MA */
 			};
@@ -3088,17 +3088,47 @@
 		cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
 			/* RESET, STANDBY */
 			mux {
-				pins = "gpio9","gpio8";
+				pins = "gpio9";
 				function = "gpio";
 			};
 			config {
-				pins = "gpio9","gpio8";
+				pins = "gpio9";
 				bias-pull-down; /* PULL DOWN */
 				drive-strength = <2>; /* 2 MA */
 				output-low;
 			};
 		};
 
+		cam_res_mgr_active: cam_res_mgr_active {
+			/* AVDD_LDO*/
+			mux {
+				pins = "gpio8";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio8";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_res_mgr_suspend: cam_res_mgr_suspend {
+			/* AVDD_LDO */
+			mux {
+				pins = "gpio8";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio8";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+				output-low;
+			};
+		};
+
+
 		trigout_a: trigout_a {
 			mux {
 				pins = "gpio90";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 6dae069..26d32a1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -162,7 +162,7 @@
 };
 
 &mdss_mdp {
-	connectors = <&sde_rscc &sde_wb>;
+	connectors = <&sde_rscc &sde_wb &sde_dp>;
 };
 
 &dsi_nt35597_truly_dsc_cmd {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index da4d41c..9672b94 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -296,7 +296,7 @@
 		qcom,supported-modes =
 			<RPMH_REGULATOR_MODE_LDO_LPM
 			 RPMH_REGULATOR_MODE_LDO_HPM>;
-		qcom,mode-threshold-currents = <0 1>;
+		qcom,mode-threshold-currents = <0 10000>;
 		pm8998_l7: regulator-l7 {
 			regulator-name = "pm8998_l7";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
@@ -479,7 +479,7 @@
 		qcom,supported-modes =
 			<RPMH_REGULATOR_MODE_LDO_LPM
 			 RPMH_REGULATOR_MODE_LDO_HPM>;
-		qcom,mode-threshold-currents = <0 1>;
+		qcom,mode-threshold-currents = <0 10000>;
 		pm8998_l17: regulator-l17 {
 			regulator-name = "pm8998_l17";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
@@ -587,7 +587,7 @@
 		qcom,supported-modes =
 			<RPMH_REGULATOR_MODE_LDO_LPM
 			 RPMH_REGULATOR_MODE_LDO_HPM>;
-		qcom,mode-threshold-currents = <0 1>;
+		qcom,mode-threshold-currents = <0 10000>;
 		pm8998_l23: regulator-l23 {
 			regulator-name = "pm8998_l23";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
@@ -624,7 +624,7 @@
 		qcom,supported-modes =
 			<RPMH_REGULATOR_MODE_LDO_LPM
 			 RPMH_REGULATOR_MODE_LDO_HPM>;
-		qcom,mode-threshold-currents = <0 1>;
+		qcom,mode-threshold-currents = <0 10000>;
 		pm8998_l25: regulator-l25 {
 			regulator-name = "pm8998_l25";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 2539aa2..e225ede 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -383,6 +383,8 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 52f9976..b78b7a0 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -395,6 +395,8 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 9a43bb6..e8fe5bc 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -571,6 +571,9 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -602,13 +605,13 @@
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
 CONFIG_CORESIGHT_DUMMY=y
+CONFIG_PFK=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index ab7268f..ca923f1 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -589,6 +589,9 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_FUSE_FS=y
@@ -666,13 +669,13 @@
 CONFIG_CORESIGHT_TGU=y
 CONFIG_CORESIGHT_HWEVENT=y
 CONFIG_CORESIGHT_DUMMY=y
+CONFIG_PFK=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c
index 64d7ac7..6792e04 100644
--- a/drivers/bluetooth/btfm_slim.c
+++ b/drivers/bluetooth/btfm_slim.c
@@ -130,7 +130,8 @@
 	BTFMSLIM_DBG("port: %d ch: %d", ch->port, ch->ch);
 
 	/* Define the channel with below parameters */
-	prop.prot =  SLIM_AUTO_ISO;
+	prop.prot =  ((rates == 44100) || (rates == 88200)) ?
+			SLIM_PUSH : SLIM_AUTO_ISO;
 	prop.baser = ((rates == 44100) || (rates == 88200)) ?
 			SLIM_RATE_11025HZ : SLIM_RATE_4000HZ;
 	prop.dataf = ((rates == 48000) || (rates == 44100) ||
@@ -228,17 +229,34 @@
 
 	BTFMSLIM_INFO("port:%d, grp: %d, ch->grph:0x%x, ch->ch_hdl:0x%x ",
 		ch->port, grp, ch->grph, ch->ch_hdl);
+
+	/* For 44.1/88.2 Khz A2DP Rx, disconnect the port first */
+	if (rxport &&
+		(btfmslim->sample_rate == 44100 ||
+		 btfmslim->sample_rate == 88200)) {
+		BTFMSLIM_DBG("disconnecting the ports, removing the channel");
+		ret = slim_disconnect_ports(btfmslim->slim_pgd,
+				&ch->port_hdl, 1);
+		if (ret < 0) {
+			BTFMSLIM_ERR("slim_disconnect_ports failed ret[%d]",
+				ret);
+		}
+	}
+
 	/* Remove the channel immediately*/
 	ret = slim_control_ch(btfmslim->slim_pgd, (grp ? ch->grph : ch->ch_hdl),
 			SLIM_CH_REMOVE, true);
 	if (ret < 0) {
 		BTFMSLIM_ERR("slim_control_ch failed ret[%d]", ret);
-		ret = slim_disconnect_ports(btfmslim->slim_pgd,
-			&ch->port_hdl, 1);
-		if (ret < 0) {
-			BTFMSLIM_ERR("slim_disconnect_ports failed ret[%d]",
-				ret);
-			goto error;
+		if (btfmslim->sample_rate != 44100 &&
+			btfmslim->sample_rate != 88200) {
+			ret = slim_disconnect_ports(btfmslim->slim_pgd,
+				&ch->port_hdl, 1);
+			if (ret < 0) {
+				BTFMSLIM_ERR("disconnect_ports failed ret[%d]",
+					 ret);
+				goto error;
+			}
 		}
 	}
 
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 2dbba83..9f2bf90 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -88,8 +88,12 @@
 
 	BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
 	if (rxport) {
-		if (enable) {
-			/* For SCO Rx, A2DP Rx */
+		BTFMSLIM_DBG("sample rate is %d", btfmslim->sample_rate);
+		if (enable &&
+			btfmslim->sample_rate != 44100 &&
+			btfmslim->sample_rate != 88200) {
+			BTFMSLIM_DBG("setting multichannel bit");
+			/* For SCO Rx, A2DP Rx other than 44.1 and 88.2Khz */
 			if (port_num < 24) {
 				rxport_num = port_num - 16;
 				reg_val = 0x01 << rxport_num;
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 8a28212..3058ce3 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -117,11 +117,11 @@
 	return offset;
 }
 
-static inline int buf_num_pages(uint64_t buf, ssize_t len)
+static inline uint64_t buf_num_pages(uint64_t buf, size_t len)
 {
 	uint64_t start = buf_page_start(buf) >> PAGE_SHIFT;
 	uint64_t end = (((uint64_t) buf + len - 1) & PAGE_MASK) >> PAGE_SHIFT;
-	int nPages = end - start + 1;
+	uint64_t nPages = end - start + 1;
 	return nPages;
 }
 
@@ -153,7 +153,7 @@
 	struct fastrpc_file *fl;
 	void *virt;
 	uint64_t phys;
-	ssize_t size;
+	size_t size;
 };
 
 struct fastrpc_ctx_lst;
@@ -179,7 +179,7 @@
 	unsigned int *attrs;
 	struct fastrpc_mmap **maps;
 	struct fastrpc_buf *buf;
-	ssize_t used;
+	size_t used;
 	struct fastrpc_file *fl;
 	uint32_t sc;
 	struct overlap *overs;
@@ -268,9 +268,9 @@
 	struct dma_buf_attachment *attach;
 	struct ion_handle *handle;
 	uint64_t phys;
-	ssize_t size;
-	uintptr_t __user va;
-	ssize_t len;
+	size_t size;
+	uintptr_t va;
+	size_t len;
 	int refs;
 	uintptr_t raddr;
 	int uncached;
@@ -424,12 +424,15 @@
 }
 
 static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd,
-		uintptr_t __user va, ssize_t len, int mflags, int refs,
+		uintptr_t va, size_t len, int mflags, int refs,
 		struct fastrpc_mmap **ppmap)
 {
 	struct fastrpc_apps *me = &gfa;
 	struct fastrpc_mmap *match = NULL, *map = NULL;
 	struct hlist_node *n;
+
+	if ((va + len) < va)
+		return -EOVERFLOW;
 	if (mflags == ADSP_MMAP_HEAP_ADDR ||
 				 mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
 		spin_lock(&me->hlock);
@@ -465,17 +468,16 @@
 	return -ENOTTY;
 }
 
-static int dma_alloc_memory(phys_addr_t *region_start, ssize_t size)
+static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size)
 {
 	struct fastrpc_apps *me = &gfa;
-	void *vaddr = NULL;
 
 	if (me->dev == NULL) {
 		pr_err("device adsprpc-mem is not initialized\n");
 		return -ENODEV;
 	}
-	vaddr = dma_alloc_coherent(me->dev, size, region_start, GFP_KERNEL);
-	if (!vaddr) {
+	*vaddr = dma_alloc_coherent(me->dev, size, region_phys, GFP_KERNEL);
+	if (!*vaddr) {
 		pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n",
 						(unsigned int)size);
 		return -ENOMEM;
@@ -484,7 +486,7 @@
 }
 
 static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
-			       ssize_t len, struct fastrpc_mmap **ppmap)
+			       size_t len, struct fastrpc_mmap **ppmap)
 {
 	struct fastrpc_mmap *match = NULL, *map;
 	struct hlist_node *n;
@@ -560,7 +562,7 @@
 		}
 		if (map->phys) {
 			dma_free_coherent(me->dev, map->size,
-					&(map->va), map->phys);
+				(void *)map->va, (dma_addr_t)map->phys);
 		}
 	} else {
 		int destVM[1] = {VMID_HLOS};
@@ -603,7 +605,7 @@
 					struct fastrpc_session_ctx **session);
 
 static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
-	unsigned int attr, uintptr_t __user va, ssize_t len, int mflags,
+	unsigned int attr, uintptr_t va, size_t len, int mflags,
 	struct fastrpc_mmap **ppmap)
 {
 	struct fastrpc_apps *me = &gfa;
@@ -613,7 +615,8 @@
 	struct fastrpc_channel_ctx *chan = &apps->channel[cid];
 	struct fastrpc_mmap *map = NULL;
 	unsigned long attrs;
-	phys_addr_t region_start = 0;
+	dma_addr_t region_phys = 0;
+	void *region_vaddr = NULL;
 	unsigned long flags;
 	int err = 0, vmid;
 
@@ -633,12 +636,13 @@
 				mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
 		map->apps = me;
 		map->fl = NULL;
-		VERIFY(err, !dma_alloc_memory(&region_start, len));
+		VERIFY(err, !dma_alloc_memory(&region_phys, &region_vaddr,
+						 len));
 		if (err)
 			goto bail;
-		map->phys = (uintptr_t)region_start;
+		map->phys = (uintptr_t)region_phys;
 		map->size = len;
-		map->va = (uintptr_t __user)map->phys;
+		map->va = (uintptr_t)region_vaddr;
 	} else {
 		if (map->attr && (map->attr & FASTRPC_ATTR_KEEP_MAP)) {
 			pr_info("adsprpc: buffer mapped with persist attr %x\n",
@@ -740,7 +744,7 @@
 	return err;
 }
 
-static int fastrpc_buf_alloc(struct fastrpc_file *fl, ssize_t size,
+static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
 			     struct fastrpc_buf **obuf)
 {
 	int err = 0, vmid;
@@ -1118,7 +1122,7 @@
 	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
 	int handles, bufs = inbufs + outbufs;
 	uintptr_t args;
-	ssize_t rlen = 0, copylen = 0, metalen = 0;
+	size_t rlen = 0, copylen = 0, metalen = 0;
 	int i, oix;
 	int err = 0;
 	int mflags = 0;
@@ -1132,8 +1136,8 @@
 	ipage = pages;
 
 	for (i = 0; i < bufs; ++i) {
-		uintptr_t __user buf = (uintptr_t __user)lpra[i].buf.pv;
-		ssize_t len = lpra[i].buf.len;
+		uintptr_t buf = (uintptr_t)lpra[i].buf.pv;
+		size_t len = lpra[i].buf.len;
 
 		if (ctx->fds[i] && (ctx->fds[i] != -1))
 			fastrpc_mmap_create(ctx->fl, ctx->fds[i],
@@ -1149,14 +1153,14 @@
 			goto bail;
 		ipage += 1;
 	}
-	metalen = copylen = (ssize_t)&ipage[0] + (sizeof(uint64_t) * M_FDLIST) +
+	metalen = copylen = (size_t)&ipage[0] + (sizeof(uint64_t) * M_FDLIST) +
 				 (sizeof(uint32_t) * M_CRCLIST);
 
 	/* calculate len requreed for copying */
 	for (oix = 0; oix < inbufs + outbufs; ++oix) {
 		int i = ctx->overps[oix]->raix;
 		uintptr_t mstart, mend;
-		ssize_t len = lpra[i].buf.len;
+		size_t len = lpra[i].buf.len;
 
 		if (!len)
 			continue;
@@ -1206,7 +1210,7 @@
 	for (i = 0; rpra && i < inbufs + outbufs; ++i) {
 		struct fastrpc_mmap *map = ctx->maps[i];
 		uint64_t buf = ptr_to_uint64(lpra[i].buf.pv);
-		ssize_t len = lpra[i].buf.len;
+		size_t len = lpra[i].buf.len;
 
 		rpra[i].buf.pv = 0;
 		rpra[i].buf.len = len;
@@ -1215,7 +1219,7 @@
 		if (map) {
 			struct vm_area_struct *vma;
 			uintptr_t offset;
-			int num = buf_num_pages(buf, len);
+			uint64_t num = buf_num_pages(buf, len);
 			int idx = list[i].pgidx;
 
 			if (map->attr & FASTRPC_ATTR_NOVA) {
@@ -1258,9 +1262,9 @@
 	for (oix = 0; oix < inbufs + outbufs; ++oix) {
 		int i = ctx->overps[oix]->raix;
 		struct fastrpc_mmap *map = ctx->maps[i];
-		ssize_t mlen;
+		size_t mlen;
 		uint64_t buf;
-		ssize_t len = lpra[i].buf.len;
+		size_t len = lpra[i].buf.len;
 
 		if (!len)
 			continue;
@@ -1647,9 +1651,9 @@
 		int mflags = 0;
 		struct {
 			int pgid;
-			int namelen;
-			int filelen;
-			int pageslen;
+			unsigned int namelen;
+			unsigned int filelen;
+			unsigned int pageslen;
 			int attrs;
 			int siglen;
 		} inbuf;
@@ -1658,14 +1662,22 @@
 		inbuf.namelen = strlen(current->comm) + 1;
 		inbuf.filelen = init->filelen;
 		fl->pd = 1;
+
+		VERIFY(err, access_ok(0, (void __user *)init->file,
+			init->filelen));
+		if (err)
+			goto bail;
 		if (init->filelen) {
 			VERIFY(err, !fastrpc_mmap_create(fl, init->filefd, 0,
 				init->file, init->filelen, mflags, &file));
 			if (err)
 				goto bail;
 		}
-
 		inbuf.pageslen = 1;
+		VERIFY(err, access_ok(1, (void __user *)init->mem,
+			init->memlen));
+		if (err)
+			goto bail;
 		VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0,
 				init->mem, init->memlen, mflags, &mem));
 		if (err)
@@ -1714,12 +1726,12 @@
 	} else if (init->flags == FASTRPC_INIT_CREATE_STATIC) {
 		remote_arg_t ra[3];
 		uint64_t phys = 0;
-		ssize_t size = 0;
+		size_t size = 0;
 		int fds[3];
 		struct {
 			int pgid;
-			int namelen;
-			int pageslen;
+			unsigned int namelen;
+			unsigned int pageslen;
 		} inbuf;
 
 		if (!init->filelen)
@@ -1961,7 +1973,7 @@
 	struct {
 		int pid;
 		uintptr_t vaddrout;
-		ssize_t size;
+		size_t size;
 	} inargs;
 
 	inargs.pid = fl->tgid;
@@ -2040,7 +2052,7 @@
 }
 
 static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
-			     ssize_t len, struct fastrpc_mmap **ppmap);
+			     size_t len, struct fastrpc_mmap **ppmap);
 
 static void fastrpc_mmap_add(struct fastrpc_mmap *map);
 
@@ -2093,12 +2105,12 @@
 	struct fastrpc_mmap *map = NULL;
 	int err = 0;
 
-	if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t __user)ud->vaddrin,
+	if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin,
 			 ud->size, ud->flags, 1, &map))
 		return 0;
 
 	VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0,
-			(uintptr_t __user)ud->vaddrin, ud->size,
+			(uintptr_t)ud->vaddrin, ud->size,
 			 ud->flags, &map));
 	if (err)
 		goto bail;
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 21ad3f9..0f07483 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -42,7 +42,7 @@
 
 struct compat_remote_buf {
 	compat_uptr_t pv;	/* buffer pointer */
-	compat_ssize_t len;	/* length of buffer */
+	compat_size_t len;	/* length of buffer */
 };
 
 union compat_remote_arg {
@@ -78,13 +78,13 @@
 	compat_int_t fd;	/* ion fd */
 	compat_uint_t flags;	/* flags for dsp to map with */
 	compat_uptr_t vaddrin;	/* optional virtual address */
-	compat_ssize_t size;	/* size */
+	compat_size_t size;	/* size */
 	compat_uptr_t vaddrout;	/* dsps virtual address */
 };
 
 struct compat_fastrpc_ioctl_munmap {
 	compat_uptr_t vaddrout;	/* address to unmap */
-	compat_ssize_t size;	/* size */
+	compat_size_t size;	/* size */
 };
 
 struct compat_fastrpc_ioctl_init {
@@ -128,7 +128,7 @@
 			unsigned int cmd)
 {
 	compat_uint_t u, sc;
-	compat_ssize_t s;
+	compat_size_t s;
 	compat_uptr_t p;
 	struct fastrpc_ioctl_invoke_crc *inv;
 	union compat_remote_arg *pra32;
@@ -190,7 +190,7 @@
 {
 	compat_uint_t u;
 	compat_int_t i;
-	compat_ssize_t s;
+	compat_size_t s;
 	compat_uptr_t p;
 	int err;
 
@@ -224,7 +224,7 @@
 			struct fastrpc_ioctl_munmap __user *unmap)
 {
 	compat_uptr_t p;
-	compat_ssize_t s;
+	compat_size_t s;
 	int err;
 
 	err = get_user(p, &unmap32->vaddrout);
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index e2f8983..535160a 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -122,7 +122,7 @@
 
 struct remote_buf64 {
 	uint64_t pv;
-	int64_t len;
+	uint64_t len;
 };
 
 struct remote_dma_handle64 {
@@ -141,7 +141,7 @@
 
 struct remote_buf {
 	void *pv;		/* buffer pointer */
-	ssize_t len;		/* length of buffer */
+	size_t len;		/* length of buffer */
 };
 
 struct remote_dma_handle {
@@ -181,30 +181,30 @@
 
 struct fastrpc_ioctl_init {
 	uint32_t flags;		/* one of FASTRPC_INIT_* macros */
-	uintptr_t __user file;	/* pointer to elf file */
-	int32_t filelen;	/* elf file length */
+	uintptr_t file;		/* pointer to elf file */
+	uint32_t filelen;	/* elf file length */
 	int32_t filefd;		/* ION fd for the file */
-	uintptr_t __user mem;	/* mem for the PD */
-	int32_t memlen;		/* mem length */
+	uintptr_t mem;		/* mem for the PD */
+	uint32_t memlen;	/* mem length */
 	int32_t memfd;		/* ION fd for the mem */
 };
 
 struct fastrpc_ioctl_init_attrs {
 		struct fastrpc_ioctl_init init;
 		int attrs;
-		int siglen;
+		unsigned int siglen;
 };
 
 struct fastrpc_ioctl_munmap {
 	uintptr_t vaddrout;	/* address to unmap */
-	ssize_t size;		/* size */
+	size_t size;		/* size */
 };
 
 struct fastrpc_ioctl_mmap {
 	int fd;				/* ion fd */
 	uint32_t flags;			/* flags for dsp to map with */
-	uintptr_t __user *vaddrin;	/* optional virtual address */
-	ssize_t size;			/* size */
+	uintptr_t vaddrin;		/* optional virtual address */
+	size_t size;			/* size */
 	uintptr_t vaddrout;		/* dsps virtual address */
 };
 
@@ -216,9 +216,9 @@
 };
 
 struct fastrpc_ioctl_perf {			/* kernel performance data */
-	uintptr_t __user data;
+	uintptr_t data;
 	uint32_t numkeys;
-	uintptr_t __user keys;
+	uintptr_t keys;
 };
 
 #define FASTRPC_CONTROL_LATENCY   (1)
@@ -269,7 +269,7 @@
 static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg64_t *pra,
 							uint32_t sc)
 {
-	int len = REMOTE_SCALARS_LENGTH(sc);
+	unsigned int len = REMOTE_SCALARS_LENGTH(sc);
 
 	return (struct smq_invoke_buf *)(&pra[len]);
 }
@@ -277,7 +277,7 @@
 static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc,
 						struct smq_invoke_buf *buf)
 {
-	int nTotal = REMOTE_SCALARS_LENGTH(sc);
+	unsigned int nTotal = REMOTE_SCALARS_LENGTH(sc);
 
 	return (struct smq_phy_page *)(&buf[nTotal]);
 }
diff --git a/drivers/clk/qcom/clk-cpu-a7.c b/drivers/clk/qcom/clk-cpu-a7.c
index c0cc00f8..3e8a75d 100644
--- a/drivers/clk/qcom/clk-cpu-a7.c
+++ b/drivers/clk/qcom/clk-cpu-a7.c
@@ -664,6 +664,11 @@
 	/* Put proxy vote for APSS PLL */
 	clk_prepare_enable(apcs_cpu_pll.clkr.hw.clk);
 
+	/* Reconfigure APSS RCG */
+	ret = clk_set_rate(apcs_clk.clkr.hw.clk, sys_apc0_aux_clk.rrate);
+	if (ret)
+		dev_err(&pdev->dev, "Unable to set aux rate on apcs_clk\n");
+
 	/* Set to TURBO boot frequency */
 	ret = clk_set_rate(apcs_clk.clkr.hw.clk, a7cc_clk_init_rate);
 	if (ret)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 609ae52..5318a5f 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1075,6 +1075,7 @@
 		for (cnt = 0; cnt < length; cnt++)
 			cmdbuf[dsi_ctrl->cmd_len + cnt] = buffer[cnt];
 
+		msm_gem_sync(dsi_ctrl->tx_cmd_buf);
 		dsi_ctrl->cmd_len += length;
 
 		if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) {
@@ -2222,6 +2223,8 @@
 	if (dsi_ctrl->hw.ops.clear_interrupt_status)
 		dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, 0x0);
 
+	SDE_EVT32_IRQ(dsi_ctrl->cell_index, status, errors);
+
 	/* handle DSI error recovery */
 	if (status & DSI_ERROR)
 		dsi_ctrl_handle_error_status(dsi_ctrl, errors);
@@ -2281,7 +2284,7 @@
  * @dsi_ctrl: Pointer to associated dsi_ctrl structure
  * Returns: Zero on success
  */
-static int dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl)
+static int _dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl)
 {
 	int irq_num, rc;
 
@@ -2475,8 +2478,6 @@
 		}
 	}
 
-	dsi_ctrl_setup_isr(dsi_ctrl);
-
 	dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
 	dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
 
@@ -2488,6 +2489,25 @@
 	return rc;
 }
 
+/**
+ * dsi_ctrl_isr_configure() - API to register/deregister dsi isr
+ * @dsi_ctrl:              DSI controller handle.
+ * @enable:		   variable to control register/deregister isr
+ */
+void dsi_ctrl_isr_configure(struct dsi_ctrl *dsi_ctrl, bool enable)
+{
+	if (!dsi_ctrl)
+		return;
+
+	mutex_lock(&dsi_ctrl->ctrl_lock);
+	if (enable)
+		_dsi_ctrl_setup_isr(dsi_ctrl);
+	else
+		_dsi_ctrl_destroy_isr(dsi_ctrl);
+
+	mutex_unlock(&dsi_ctrl->ctrl_lock);
+}
+
 int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl)
 {
 	if (!dsi_ctrl)
@@ -2563,8 +2583,6 @@
 
 	mutex_lock(&dsi_ctrl->ctrl_lock);
 
-	_dsi_ctrl_destroy_isr(dsi_ctrl);
-
 	rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0);
 	if (rc) {
 		pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
@@ -3255,6 +3273,28 @@
 }
 
 /**
+ * dsi_ctrl_irq_update() - Put a irq vote to process DSI error
+ *				interrupts at any time.
+ * @dsi_ctrl:              DSI controller handle.
+ * @enable:		   variable to enable/disable irq
+ */
+void dsi_ctrl_irq_update(struct dsi_ctrl *dsi_ctrl, bool enable)
+{
+	if (!dsi_ctrl)
+		return;
+
+	mutex_lock(&dsi_ctrl->ctrl_lock);
+	if (enable)
+		dsi_ctrl_enable_status_interrupt(dsi_ctrl,
+					DSI_SINT_ERROR, NULL);
+	else
+		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
+					DSI_SINT_ERROR);
+
+	mutex_unlock(&dsi_ctrl->ctrl_lock);
+}
+
+/**
  * dsi_ctrl_drv_register() - register platform driver for dsi controller
  */
 void dsi_ctrl_drv_register(void)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 80b91ca..8850df4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -703,4 +703,18 @@
 int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len,
 		u32 *flags);
 
+/**
+ * dsi_ctrl_isr_configure() - API to register/deregister dsi isr
+ * @dsi_ctrl:              DSI controller handle.
+ * @enable:		   variable to control register/deregister isr
+ */
+void dsi_ctrl_isr_configure(struct dsi_ctrl *dsi_ctrl, bool enable);
+
+/**
+ * dsi_ctrl_irq_update() - Put a irq vote to process DSI error
+ *				interrupts at any time.
+ * @dsi_ctrl:              DSI controller handle.
+ * @enable:		   variable to control enable/disable irq line
+ */
+void dsi_ctrl_irq_update(struct dsi_ctrl *dsi_ctrl, bool enable);
 #endif /* _DSI_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index d92a71d..985cb51 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -2369,6 +2369,40 @@
 	return 0;
 }
 
+static void dsi_display_ctrl_isr_configure(struct dsi_display *display, bool en)
+{
+	int i;
+	struct dsi_display_ctrl *ctrl;
+
+	if (!display)
+		return;
+
+	for (i = 0; (i < display->ctrl_count) &&
+			(i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
+		ctrl = &display->ctrl[i];
+		if (!ctrl)
+			continue;
+		dsi_ctrl_isr_configure(ctrl->ctrl, en);
+	}
+}
+
+static void dsi_display_ctrl_irq_update(struct dsi_display *display, bool en)
+{
+	int i;
+	struct dsi_display_ctrl *ctrl;
+
+	if (!display)
+		return;
+
+	for (i = 0; (i < display->ctrl_count) &&
+			(i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
+		ctrl = &display->ctrl[i];
+		if (!ctrl)
+			continue;
+		dsi_ctrl_irq_update(ctrl->ctrl, en);
+	}
+}
+
 int dsi_pre_clkoff_cb(void *priv,
 			   enum dsi_clk_type clk,
 			   enum dsi_clk_state new_state)
@@ -2485,6 +2519,9 @@
 		 */
 		if (display->phy_idle_power_off || mmss_clamp)
 			dsi_display_phy_idle_on(display, mmss_clamp);
+
+		/* enable dsi to serve irqs */
+		dsi_display_ctrl_irq_update(display, true);
 	}
 	if (clk & DSI_LINK_CLK) {
 		if (display->ulps_enabled) {
@@ -2514,6 +2551,8 @@
 
 	if ((clk_type & DSI_CORE_CLK) &&
 	    (curr_state == DSI_CLK_OFF)) {
+		/* dsi will not be able to serve irqs from here */
+		dsi_display_ctrl_irq_update(display, false);
 
 		rc = dsi_display_phy_power_off(display);
 		if (rc)
@@ -4752,6 +4791,9 @@
 		}
 	}
 
+	/* Set up ctrl isr before enabling core clk */
+	dsi_display_ctrl_isr_configure(display, true);
+
 	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
 			DSI_CORE_CLK, DSI_CLK_ON);
 	if (rc) {
@@ -5280,6 +5322,9 @@
 		pr_err("[%s] failed to disable DSI clocks, rc=%d\n",
 		       display->name, rc);
 
+	/* destrory dsi isr set up */
+	dsi_display_ctrl_isr_configure(display, false);
+
 	rc = dsi_panel_post_unprepare(display->panel);
 	if (rc)
 		pr_err("[%s] panel post-unprepare failed, rc=%d\n",
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e5c3082..cc09256 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -727,6 +727,7 @@
 void msm_gem_shrinker_init(struct drm_device *dev);
 void msm_gem_shrinker_cleanup(struct drm_device *dev);
 
+void msm_gem_sync(struct drm_gem_object *obj);
 int msm_gem_mmap_obj(struct drm_gem_object *obj,
 			struct vm_area_struct *vma);
 int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index a015379..d9aad88 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -150,6 +150,24 @@
 	/* when we start tracking the pin count, then do something here */
 }
 
+void msm_gem_sync(struct drm_gem_object *obj)
+{
+	struct msm_gem_object *msm_obj;
+
+	if (!obj)
+		return;
+
+	msm_obj = to_msm_bo(obj);
+
+	/*
+	 * dma_sync_sg_for_device synchronises a single contiguous or
+	 * scatter/gather mapping for the CPU and device.
+	 */
+	dma_sync_sg_for_device(obj->dev->dev, msm_obj->sgt->sgl,
+		       msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+}
+
+
 int msm_gem_mmap_obj(struct drm_gem_object *obj,
 		struct vm_area_struct *vma)
 {
diff --git a/drivers/gpu/drm/msm/sde/sde_core_perf.c b/drivers/gpu/drm/msm/sde/sde_core_perf.c
index 3879d4d..fa53464 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_perf.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_perf.c
@@ -29,6 +29,8 @@
 
 #define SDE_PERF_MODE_STRING_SIZE	128
 
+static DEFINE_MUTEX(sde_core_perf_lock);
+
 /**
  * enum sde_perf_mode - performance tuning mode
  * @SDE_PERF_MODE_NORMAL: performance controlled by user mode client
@@ -303,8 +305,7 @@
 }
 
 static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
-		struct drm_crtc *crtc, u32 bus_id,
-		struct sde_core_perf_params *crtc_perf)
+		struct drm_crtc *crtc, u32 bus_id)
 {
 	u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota;
 	struct sde_core_perf_params perf = { { 0 } };
@@ -313,6 +314,7 @@
 	struct drm_crtc *tmp_crtc;
 	struct sde_crtc_state *sde_cstate;
 	struct msm_drm_private *priv = kms->dev->dev_private;
+	struct sde_crtc *sde_crtc;
 
 	u64 tmp_max_per_pipe_ib;
 	u64 tmp_bw_ctl;
@@ -322,18 +324,12 @@
 		    _is_crtc_client_type_matches(tmp_crtc, curr_client_type,
 								&kms->perf)) {
 
-			if (crtc->base.id == tmp_crtc->base.id) {
-				/* for current crtc use the cached values */
-				tmp_max_per_pipe_ib =
-					crtc_perf->max_per_pipe_ib[bus_id];
-				tmp_bw_ctl = crtc_perf->bw_ctl[bus_id];
-			} else {
-				sde_cstate = to_sde_crtc_state(tmp_crtc->state);
-				tmp_max_per_pipe_ib =
-				  sde_cstate->new_perf.max_per_pipe_ib[bus_id];
-				tmp_bw_ctl =
-				  sde_cstate->new_perf.bw_ctl[bus_id];
-			}
+			/* use current perf, which are the values voted */
+			sde_crtc = to_sde_crtc(tmp_crtc);
+			tmp_max_per_pipe_ib =
+			  sde_crtc->cur_perf.max_per_pipe_ib[bus_id];
+			tmp_bw_ctl =
+			  sde_crtc->cur_perf.bw_ctl[bus_id];
 
 			perf.max_per_pipe_ib[bus_id] =
 				max(perf.max_per_pipe_ib[bus_id],
@@ -468,30 +464,25 @@
 		SDE_DEBUG("Release BW crtc=%d\n", crtc->base.id);
 		for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
 			sde_crtc->cur_perf.bw_ctl[i] = 0;
-			_sde_core_perf_crtc_update_bus(kms, crtc, i,
-				&sde_crtc->cur_perf);
+			_sde_core_perf_crtc_update_bus(kms, crtc, i);
 		}
 	}
 }
 
-static u64 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms,
-	struct sde_core_perf_params *crct_perf, struct drm_crtc *crtc)
+static u64 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms)
 {
 	u64 clk_rate = kms->perf.perf_tune.min_core_clk;
 	struct drm_crtc *tmp_crtc;
-	struct sde_crtc_state *sde_cstate;
+	struct sde_crtc *sde_crtc;
 	u64 tmp_rate;
 
 	drm_for_each_crtc(tmp_crtc, kms->dev) {
 		if (_sde_core_perf_crtc_is_power_on(tmp_crtc)) {
 
-			if (crtc->base.id == tmp_crtc->base.id) {
-				/* for current CRTC, use the cached value */
-				tmp_rate = crct_perf->core_clk_rate;
-			} else {
-				sde_cstate = to_sde_crtc_state(tmp_crtc->state);
-				tmp_rate = sde_cstate->new_perf.core_clk_rate;
-			}
+			/* use current perf, which are the values voted */
+			sde_crtc = to_sde_crtc(tmp_crtc);
+			tmp_rate = sde_crtc->cur_perf.core_clk_rate;
+
 			clk_rate = max(tmp_rate, clk_rate);
 
 			clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate);
@@ -540,6 +531,8 @@
 	SDE_DEBUG("crtc:%d stop_req:%d core_clk:%llu\n",
 			crtc->base.id, stop_req, kms->perf.core_clk_rate);
 
+	mutex_lock(&sde_core_perf_lock);
+
 	/*
 	 * cache the performance numbers in the crtc prior to the
 	 * crtc kickoff, so the same numbers are used during the
@@ -641,7 +634,7 @@
 
 	for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
 		if (update_bus & BIT(i))
-			_sde_core_perf_crtc_update_bus(kms, crtc, i, old);
+			_sde_core_perf_crtc_update_bus(kms, crtc, i);
 	}
 
 	/*
@@ -649,7 +642,7 @@
 	 * bandwidth is available before clock rate is increased.
 	 */
 	if (update_clk) {
-		clk_rate = _sde_core_perf_get_core_clk_rate(kms, old, crtc);
+		clk_rate = _sde_core_perf_get_core_clk_rate(kms);
 
 		SDE_EVT32(kms->dev, stop_req, clk_rate, params_changed,
 			old->core_clk_rate, new->core_clk_rate);
@@ -658,12 +651,15 @@
 		if (ret) {
 			SDE_ERROR("failed to set %s clock rate %llu\n",
 					kms->perf.clk_name, clk_rate);
+			mutex_unlock(&sde_core_perf_lock);
 			return;
 		}
 
 		kms->perf.core_clk_rate = clk_rate;
 		SDE_DEBUG("update clk rate = %lld HZ\n", clk_rate);
 	}
+	mutex_unlock(&sde_core_perf_lock);
+
 }
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 94c7f40..9cdef88 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -3501,6 +3501,9 @@
 	if (dump_status)
 		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus");
 
+	/* optionally generate a panic instead of performing a h/w reset */
+	SDE_DBG_CTRL("stop_ftrace", "reset_hw_panic");
+
 	for (i = 0; i < sde_crtc->num_mixers; ++i) {
 		ctl = sde_crtc->mixers[i].hw_ctl;
 		if (!ctl || !ctl->ops.reset)
@@ -3618,10 +3621,11 @@
 
 		/*
 		 * For inline ASYNC modes, the flush bits are not written
-		 * to hardware atomically, so avoid using it if a video
-		 * mode encoder is active on this CRTC.
+		 * to hardware atomically. This is not fully supported for
+		 * non-command mode encoders, so force SYNC mode if any
+		 * of them are attached to the CRTC.
 		 */
-		if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO) {
+		if (sde_encoder_get_intf_mode(encoder) != INTF_MODE_CMD) {
 			cstate->sbuf_cfg.rot_op_mode =
 				SDE_CTL_ROT_OP_MODE_INLINE_SYNC;
 			return false;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index b6888df..0ed994b 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -2140,7 +2140,7 @@
 		mutex_lock(&sde_enc->rc_lock);
 
 		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
-			SDE_ERROR_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
+			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
 					sw_event, sde_enc->rc_state);
 			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
 					SDE_EVTLOG_ERROR);
@@ -2768,18 +2768,35 @@
 	}
 }
 
+int sde_encoder_idle_request(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid drm encoder\n");
+		return -EINVAL;
+	}
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	sde_encoder_resource_control(&sde_enc->base,
+						SDE_ENC_RC_EVENT_ENTER_IDLE);
+
+	return 0;
+}
+
 static void sde_encoder_off_work(struct kthread_work *work)
 {
 	struct sde_encoder_virt *sde_enc = container_of(work,
 			struct sde_encoder_virt, delayed_off_work.work);
+	struct drm_encoder *drm_enc;
 
 	if (!sde_enc) {
 		SDE_ERROR("invalid sde encoder\n");
 		return;
 	}
+	drm_enc = &sde_enc->base;
 
-	sde_encoder_resource_control(&sde_enc->base,
-						SDE_ENC_RC_EVENT_ENTER_IDLE);
+	sde_encoder_idle_request(drm_enc);
 }
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index f8a3cf3..937bd18 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -155,6 +155,14 @@
 int sde_encoder_wait_for_event(struct drm_encoder *drm_encoder,
 						enum msm_event_wait event);
 
+/**
+ * sde_encoder_idle_request - request for idle request to avoid 4 vsync cycle
+ *                            to turn off the clocks.
+ * @encoder:	encoder pointer
+ * Returns: 0 on success, errorcode otherwise
+ */
+int sde_encoder_idle_request(struct drm_encoder *drm_enc);
+
 /*
  * sde_encoder_get_intf_mode - get interface mode of the given encoder
  * @encoder: Pointer to drm encoder object
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
index cf65784..6ccf957 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
@@ -481,6 +481,7 @@
 	cmd1 |= (cfg->op == REG_DMA_WRITE) ? (BIT(22)) : 0;
 	cmd1 |= (SIZE_DWORD(cfg->dma_buf->index) & MAX_DWORDS_SZ);
 
+	msm_gem_sync(cfg->dma_buf->buf);
 	SET_UP_REG_DMA_REG(hw, reg_dma);
 	SDE_REG_WRITE(&hw, REG_DMA_OP_MODE_OFF, BIT(0));
 	SDE_REG_WRITE(&hw, reg_dma_clear_status_off,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index e7aa6ea..0d85c53 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -260,13 +260,13 @@
  */
 static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx,
 		const struct sde_format *fmt,
-		bool blend_enabled, u32 flags,
+		bool const_alpha_en, u32 flags,
 		enum sde_sspp_multirect_index rect_mode)
 {
 	struct sde_hw_blk_reg_map *c;
 	u32 chroma_samp, unpack, src_format;
 	u32 opmode = 0;
-	u32 fast_clear = 0;
+	u32 alpha_en_mask = 0;
 	u32 op_mode_off, unpack_pat_off, format_off;
 	u32 idx;
 
@@ -329,11 +329,10 @@
 			SDE_FETCH_CONFIG_RESET_VALUE |
 			ctx->mdp->highest_bank_bit << 18);
 		if (IS_UBWC_20_SUPPORTED(ctx->catalog->ubwc_version)) {
-			fast_clear = (fmt->alpha_enable && blend_enabled) ?
-				BIT(31) : 0;
+			alpha_en_mask = const_alpha_en ? BIT(31) : 0;
 			SDE_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
-					fast_clear | (ctx->mdp->ubwc_swizzle) |
-					(ctx->mdp->highest_bank_bit << 4));
+				alpha_en_mask | (ctx->mdp->ubwc_swizzle) |
+				(ctx->mdp->highest_bank_bit << 4));
 		}
 	}
 
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index f4b362f..bbd6f45 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -2323,7 +2323,8 @@
 	if (num_crtcs == 0) {
 		DRM_DEBUG("all crtcs are already in the off state\n");
 		drm_atomic_state_free(state);
-		goto suspended;
+		sde_kms->suspend_block = true;
+		goto unlock;
 	}
 
 	/* commit the "disable all" state */
@@ -2334,9 +2335,24 @@
 		goto unlock;
 	}
 
-suspended:
 	sde_kms->suspend_block = true;
 
+	drm_for_each_connector(conn, ddev) {
+		uint64_t lp;
+
+		lp = sde_connector_get_lp(conn);
+		if (lp != SDE_MODE_DPMS_LP2)
+			continue;
+
+		ret = sde_encoder_wait_for_event(conn->encoder,
+						MSM_ENC_TX_COMPLETE);
+		if (ret && ret != -EWOULDBLOCK)
+			SDE_ERROR(
+				"[enc: %d] wait for commit done returned %d\n",
+				conn->encoder->base.id, ret);
+		else if (!ret)
+			sde_encoder_idle_request(conn->encoder);
+	}
 unlock:
 	if (ret == -EDEADLK) {
 		drm_modeset_backoff(&ctx);
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 9f27286..f2f870f 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -2810,6 +2810,7 @@
 	bool parallel_fetch_qualified = true;
 	enum sde_sspp_multirect_mode mode = SDE_SSPP_MULTIRECT_NONE;
 	const struct msm_format *msm_fmt;
+	bool const_alpha_enable = true;
 
 	for (i = 0; i < R_MAX; i++) {
 		drm_state[i] = i ? plane->r1 : plane->r0;
@@ -2877,6 +2878,10 @@
 		if (sde_plane[i]->is_virtual)
 			mode = sde_plane_get_property(pstate[i],
 					PLANE_PROP_MULTIRECT_MODE);
+
+		if (pstate[i]->const_alpha_en != const_alpha_enable)
+			const_alpha_enable = false;
+
 	}
 
 	buffer_lines = 2 * max_tile_height;
@@ -2936,8 +2941,10 @@
 		break;
 	}
 
-	for (i = 0; i < R_MAX; i++)
+	for (i = 0; i < R_MAX; i++) {
 		pstate[i]->multirect_mode = mode;
+		pstate[i]->const_alpha_en = const_alpha_enable;
+	}
 
 	if (mode == SDE_SSPP_MULTIRECT_NONE)
 		return -EINVAL;
@@ -3138,6 +3145,29 @@
 	return sde_vbif_halt_plane_xin(sde_kms, xin_id, clk_ctrl);
 }
 
+
+static inline int _sde_plane_power_enable(struct drm_plane *plane, bool enable)
+{
+	struct msm_drm_private *priv;
+	struct sde_kms *sde_kms;
+
+	if (!plane->dev || !plane->dev->dev_private) {
+		SDE_ERROR("invalid drm device\n");
+		return -EINVAL;
+	}
+
+	priv = plane->dev->dev_private;
+	if (!priv->kms) {
+		SDE_ERROR("invalid kms\n");
+		return -EINVAL;
+	}
+
+	sde_kms = to_sde_kms(priv->kms);
+
+	return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
+									enable);
+}
+
 static void sde_plane_cleanup_fb(struct drm_plane *plane,
 		struct drm_plane_state *old_state)
 {
@@ -3163,6 +3193,13 @@
 			       psde->pipe - SSPP_VIG0);
 
 		/* halt this plane now */
+		ret = _sde_plane_power_enable(plane, true);
+		if (ret) {
+			SDE_ERROR("power resource enable failed with %d", ret);
+			SDE_EVT32(ret);
+			return;
+		}
+
 		ret = _sde_plane_fetch_halt(plane);
 		if (ret) {
 			SDE_ERROR_PLANE(psde,
@@ -3171,6 +3208,7 @@
 			SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
 				       ret, SDE_EVTLOG_ERROR);
 		}
+		_sde_plane_power_enable(plane, false);
 	}
 
 	old_rstate = &old_pstate->rot;
@@ -3541,6 +3579,10 @@
 				pstate->excl_rect.w, pstate->excl_rect.h);
 	}
 
+	pstate->const_alpha_en = fmt->alpha_enable &&
+		(SDE_DRM_BLEND_OP_OPAQUE !=
+		 sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP));
+
 modeset_update:
 	if (!ret)
 		_sde_plane_sspp_atomic_check_mode_changed(psde,
@@ -3638,7 +3680,6 @@
 	struct drm_framebuffer *fb;
 	struct sde_rect src, dst;
 	bool q16_data = true;
-	bool blend_enabled = true;
 	int idx;
 
 	if (!plane) {
@@ -3876,12 +3917,9 @@
 		if (rstate->out_rotation & DRM_REFLECT_Y)
 			src_flags |= SDE_SSPP_FLIP_UD;
 
-		blend_enabled = (SDE_DRM_BLEND_OP_OPAQUE !=
-			sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP));
-
 		/* update format */
 		psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt,
-				blend_enabled, src_flags,
+				pstate->const_alpha_en, src_flags,
 				pstate->multirect_index);
 
 		if (psde->pipe_hw->ops.setup_cdp) {
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index d1eb399..e8b621c 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -128,6 +128,7 @@
  * @dirty:	bitmask for which pipe h/w config functions need to be updated
  * @multirect_index: index of the rectangle of SSPP
  * @multirect_mode: parallel or time multiplex multirect mode
+ * @const_alpha_en: const alpha channel is enabled for this HW pipe
  * @pending:	whether the current update is still pending
  * @defer_prepare_fb:	indicate if prepare_fb call was deferred
  * @scaler3_cfg: configuration data for scaler3
@@ -146,6 +147,7 @@
 	uint32_t dirty;
 	uint32_t multirect_index;
 	uint32_t multirect_mode;
+	bool const_alpha_en;
 	bool pending;
 	bool defer_prepare_fb;
 
diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c
index c34b198..5c72efa 100644
--- a/drivers/gpu/drm/msm/sde_dbg.c
+++ b/drivers/gpu/drm/msm/sde_dbg.c
@@ -71,7 +71,8 @@
 
 #define DBG_CTRL_STOP_FTRACE	BIT(0)
 #define DBG_CTRL_PANIC_UNDERRUN	BIT(1)
-#define DBG_CTRL_MAX			BIT(2)
+#define DBG_CTRL_RESET_HW_PANIC	BIT(2)
+#define DBG_CTRL_MAX			BIT(3)
 
 /**
  * struct sde_dbg_reg_offset - tracking for start and end of region
@@ -2709,7 +2710,6 @@
 	va_list args;
 	char *blk_name = NULL;
 
-
 	/* no debugfs controlled events are enabled, just return */
 	if (!sde_dbg_base.debugfs_ctrl)
 		return;
@@ -2738,8 +2738,16 @@
 			pr_debug("panic underrun\n");
 			panic("underrun");
 		}
+
+		if (!strcmp(blk_name, "reset_hw_panic") &&
+				sde_dbg_base.debugfs_ctrl &
+				DBG_CTRL_RESET_HW_PANIC) {
+			pr_debug("reset hw panic\n");
+			panic("reset_hw");
+		}
 	}
 
+	va_end(args);
 }
 
 
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 4244c00..40542ab 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -29,6 +29,7 @@
 
 #include "sde_power_handle.h"
 #include "sde_trace.h"
+#include "sde_dbg.h"
 
 static const char *data_bus_name[SDE_POWER_HANDLE_DBUS_ID_MAX] = {
 	[SDE_POWER_HANDLE_DBUS_ID_MNOC] = "qcom,sde-data-bus",
@@ -932,6 +933,7 @@
 			goto rsc_err;
 		}
 
+		SDE_EVT32_VERBOSE(enable, SDE_EVTLOG_FUNC_CASE1);
 		rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
 		if (rc) {
 			pr_err("clock enable failed rc:%d\n", rc);
@@ -945,6 +947,7 @@
 		sde_power_event_trigger_locked(phandle,
 				SDE_POWER_EVENT_PRE_DISABLE);
 
+		SDE_EVT32_VERBOSE(enable, SDE_EVTLOG_FUNC_CASE2);
 		msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
 
 		sde_power_rsc_update(phandle, false);
@@ -964,7 +967,9 @@
 	}
 
 end:
+	SDE_EVT32_VERBOSE(enable, SDE_EVTLOG_FUNC_EXIT);
 	mutex_unlock(&phandle->phandle_lock);
+
 	return rc;
 
 clk_err:
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 429ab01..ca4f0da 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -39,8 +39,11 @@
 /* this time is ~1ms - only wake tcs in any mode */
 #define RSC_BACKOFF_TIME_NS		 (SINGLE_TCS_EXECUTION_TIME + 100)
 
-/* this time is ~1ms - only wake TCS in mode-0 */
-#define RSC_MODE_THRESHOLD_TIME_IN_NS	(SINGLE_TCS_EXECUTION_TIME + 100)
+/**
+ * this time is ~1ms - only wake TCS in mode-0.
+ * This time must be greater than backoff time.
+ */
+#define RSC_MODE_THRESHOLD_TIME_IN_NS	(RSC_BACKOFF_TIME_NS + 2700)
 
 /* this time is ~2ms - sleep+ wake TCS in mode-1 */
 #define RSC_TIME_SLOT_0_NS		((SINGLE_TCS_EXECUTION_TIME * 2) + 100)
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 5991cd5..e123555 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -982,37 +982,8 @@
 
 /* ISENSE registers */
 #define A6XX_GMU_ISENSE_CTRL			0x1F95D
-#define A6XX_GPU_CS_ENABLE_REG			0x23120
 #define A6XX_GPU_GMU_CX_GMU_ISENSE_CTRL		0x1f95d
-#define A6XX_GPU_CS_AMP_CALIBRATION_CONTROL3	0x22d78
-#define A6XX_GPU_CS_AMP_CALIBRATION_CONTROL2	0x22d58
-#define A6XX_GPU_CS_A_SENSOR_CTRL_0		0x22d80
-#define A6XX_GPU_CS_A_SENSOR_CTRL_2		0x422da
-#define A6XX_GPU_CS_SENSOR_GENERAL_STATUS	0x2301a
-#define A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1	0x23157
-#define A6XX_GPU_CS_SENSOR_GENERAL_STATUS	0x2301a
-#define A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_0	0x2301d
-#define A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_2	0x2301f
-#define A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_4	0x23021
-#define A6XX_GPU_CS_AMP_CALIBRATION_DONE	0x23165
-#define A6XX_GPU_CS_AMP_PERIOD_CTRL		0x2316d
-#define A6XX_GPU_CS_AMP_CALIBRATION_DONE	0x23165
-
-#define CS_PWR_ON_STATUS			(10)
-#define AMP_SW_WRM_TRIM_START			(24)
-#define AMP_TRIM_TIMER				(6)
-#define AMP_SW_TRIM_START			(0)
-#define SS_AMPTRIM_DONE				(11)
-#define AMP_OFFSET_CHECK_MIN_ERR		(1)
-#define AMP_OFFSET_CHECK_MAX_ERR		(2)
-#define AMP_OUT_OF_RANGE_ERR			(4)
-#define TRIM_CNT_VALUE				(1)
-#define RUNTIME_CNT_VALUE			(16)
-#define TRIM_ENABLE				(0)
-
-#define AMP_ERR			(BIT(AMP_OFFSET_CHECK_MIN_ERR) || \
-				BIT(AMP_OFFSET_CHECK_MAX_ERR) || \
-				BIT(AMP_OUT_OF_RANGE_ERR))
+#define A6XX_GPU_CS_ENABLE_REG			0x23120
 
 /* LM registers */
 #define A6XX_GPU_GMU_CX_GMU_PWR_THRESHOLD       0x1F94D
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 770cf3b..08cd06b 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -347,7 +347,7 @@
 		.minor = 0,
 		.patchid = ANY_ID,
 		.features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_IFPC |
-			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_LM |
+			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION |
 			ADRENO_IOCOHERENT,
 		.sqefw_name = "a630_sqe.fw",
 		.zap_name = "a630_zap",
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 13fe0a7..b8006b7 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1872,8 +1872,18 @@
 				OOB_GPU_CHECK_MASK,
 				OOB_GPU_CLEAR_MASK);
 		if (error) {
+			struct gmu_device *gmu = &device->gmu;
+
 			gpudev->oob_clear(adreno_dev, OOB_GPU_CLEAR_MASK);
-			return error;
+			if (gmu->gx_gdsc &&
+				regulator_is_enabled(gmu->gx_gdsc)) {
+				/* GPU is on. Try recovery */
+				set_bit(GMU_FAULT, &gmu->flags);
+				gmu_snapshot(device);
+				error = -EINVAL;
+			} else {
+				return error;
+			}
 		}
 	}
 
@@ -1907,7 +1917,7 @@
 	 * GMU to return to the lowest idle level. This is
 	 * because some idle level transitions require VBIF and MMU.
 	 */
-	if (gpudev->wait_for_lowest_idle &&
+	if (!error && gpudev->wait_for_lowest_idle &&
 			gpudev->wait_for_lowest_idle(adreno_dev)) {
 		struct gmu_device *gmu = &device->gmu;
 
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 83dd3fb..287ea206 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -43,6 +43,8 @@
 #define A6XX_GPU_CX_REG_BASE		0x509E000
 #define A6XX_GPU_CX_REG_SIZE		0x1000
 
+#define GPU_LIMIT_THRESHOLD_ENABLE	BIT(31)
+
 static int _load_gmu_firmware(struct kgsl_device *device);
 
 static const struct adreno_vbif_data a630_vbif[] = {
@@ -758,6 +760,38 @@
 
 	a6xx_preemption_start(adreno_dev);
 	a6xx_protect_init(adreno_dev);
+
+	/*
+	 * We start LM here because we want all the following to be up
+	 * 1. GX HS
+	 * 2. SPTPRAC
+	 * 3. HFI
+	 * At this point, we are guaranteed all.
+	 */
+	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
+		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) {
+		int result;
+		struct gmu_device *gmu = &device->gmu;
+		struct device *dev = &gmu->pdev->dev;
+
+		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_PWR_THRESHOLD,
+			GPU_LIMIT_THRESHOLD_ENABLE | lm_limit(adreno_dev));
+		kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 1);
+		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_ISENSE_CTRL, 0x1);
+
+		gmu->lm_config.lm_type = 1;
+		gmu->lm_config.lm_sensor_type = 1;
+		gmu->lm_config.throttle_config = 1;
+		gmu->lm_config.idle_throttle_en = 0;
+		gmu->lm_config.acd_en = 0;
+		gmu->bcl_config = 0;
+		gmu->lm_dcvs_level = 0;
+
+		result = hfi_send_lmconfig(gmu);
+		if (result)
+			dev_err(dev, "Failure enabling limits management (%d)\n",
+			result);
+	}
 }
 
 /*
@@ -1713,80 +1747,6 @@
 	return 0;
 }
 
-#define KMASK(start, n) (GENMASK((start + n), (start)))
-
-static void isense_cold_trimm(struct kgsl_device *device)
-{
-	unsigned int reg;
-	struct gmu_device *gmu = &device->gmu;
-
-	kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 1);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_DONE, 0);
-
-	kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_ISENSE_CTRL, 0x1);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL3,
-		0x00000F8F);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL2,
-		0x00705161);
-	udelay(10);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_ENABLE_REG, 0x3);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_A_SENSOR_CTRL_0, 0x10040a);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_A_SENSOR_CTRL_2, 0x10040a);
-
-	kgsl_gmu_regread(device, A6XX_GPU_CS_SENSOR_GENERAL_STATUS, &reg);
-	if ((reg & BIT(CS_PWR_ON_STATUS)) != (1 << CS_PWR_ON_STATUS)) {
-		dev_err(&gmu->pdev->dev, "ERROR - ISENSE power-up\n");
-		return;
-	}
-
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1,
-		KMASK(AMP_TRIM_TIMER, 15), 70 << AMP_TRIM_TIMER);
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1,
-		KMASK(AMP_SW_TRIM_START, 1), 0 << AMP_SW_TRIM_START);
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_CALIBRATION_CONTROL1,
-		KMASK(AMP_SW_TRIM_START, 1), 1 << AMP_SW_TRIM_START);
-
-	if (timed_poll_check(device, A6XX_GPU_CS_SENSOR_GENERAL_STATUS,
-		BIT(SS_AMPTRIM_DONE), GMU_START_TIMEOUT,
-		BIT(SS_AMPTRIM_DONE))) {
-		dev_err(&gmu->pdev->dev, "ISENSE SS_AMPTRIM failure\n");
-		return;
-	}
-
-	kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_0, &reg);
-	if (reg & AMP_ERR) {
-		kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_0,
-			&reg);
-		dev_err(&gmu->pdev->dev,
-			"ISENSE ERROR:trimming GX 0x%08x\n", reg);
-		return;
-	}
-
-	kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_2, &reg);
-	if (reg & AMP_ERR) {
-		kgsl_gmu_regread(device, A6XX_GPU_CS_AMP_CALIBRATION_STATUS1_2,
-			&reg);
-		dev_err(&gmu->pdev->dev,
-			"ISENSE ERROR:trimming SPTPRAC 0x%08x\n", reg);
-		return;
-	}
-
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_DONE, 1);
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
-		KMASK(TRIM_CNT_VALUE, 13), 20 << TRIM_CNT_VALUE);
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
-		KMASK(RUNTIME_CNT_VALUE, 9), 50 << RUNTIME_CNT_VALUE);
-
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
-		KMASK(TRIM_ENABLE, 1), 1 << TRIM_ENABLE);
-	udelay(4);
-	kgsl_gmu_regrmw(device, A6XX_GPU_CS_AMP_PERIOD_CTRL,
-		KMASK(TRIM_ENABLE, 1), 0 << TRIM_ENABLE);
-	kgsl_gmu_regwrite(device, A6XX_GPU_CS_AMP_CALIBRATION_DONE, 1);
-
-}
-
-#define GPU_LIMIT_THRESHOLD_ENABLE	BIT(31)
 /*
  * a6xx_gmu_fw_start() - set up GMU and start FW
  * @device: Pointer to KGSL device
@@ -1867,13 +1827,6 @@
 
 	kgsl_gmu_regwrite(device, A6XX_GMU_HFI_SFR_ADDR, chipid);
 
-	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
-		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) {
-		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_PWR_THRESHOLD,
-			GPU_LIMIT_THRESHOLD_ENABLE | lm_limit(adreno_dev));
-		isense_cold_trimm(device);
-	}
-
 	/* Configure power control and bring the GMU out of reset */
 	a6xx_gmu_power_config(device);
 	ret = a6xx_gmu_start(device);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 0ab775a..6fca1e15 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -498,6 +498,7 @@
  * @sysfs_read: Count of current reads via sysfs
  * @first_read: True until the snapshot read is started
  * @gmu_fault: Snapshot collected when GMU fault happened
+ * @recovered: True if GPU was recovered after previous snapshot
  */
 struct kgsl_snapshot {
 	uint64_t ib1base;
@@ -521,6 +522,7 @@
 	unsigned int sysfs_read;
 	bool first_read;
 	bool gmu_fault;
+	bool recovered;
 };
 
 /**
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 0a7424a..df06a0d 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1343,29 +1343,27 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct gmu_device *gmu = &device->gmu;
 
-	if (!gmu->fault_count) {
-		/* Mask so there's no interrupt caused by NMI */
-		adreno_write_gmureg(adreno_dev,
-				ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF);
+	/* Mask so there's no interrupt caused by NMI */
+	adreno_write_gmureg(adreno_dev,
+			ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF);
 
-		/* Make sure the interrupt is masked before causing it */
-		wmb();
-		adreno_write_gmureg(adreno_dev,
-			ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0);
-		adreno_write_gmureg(adreno_dev,
-			ADRENO_REG_GMU_CM3_CFG, (1 << 9));
+	/* Make sure the interrupt is masked before causing it */
+	wmb();
+	adreno_write_gmureg(adreno_dev,
+		ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0);
+	adreno_write_gmureg(adreno_dev,
+		ADRENO_REG_GMU_CM3_CFG, (1 << 9));
 
-		/* Wait for the NMI to be handled */
-		wmb();
-		udelay(100);
-		kgsl_device_snapshot(device, NULL, true);
+	/* Wait for the NMI to be handled */
+	wmb();
+	udelay(100);
+	kgsl_device_snapshot(device, NULL, true);
 
-		adreno_write_gmureg(adreno_dev,
-				ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF);
-		adreno_write_gmureg(adreno_dev,
-				ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
-				(unsigned int) ~HFI_IRQ_MASK);
-	}
+	adreno_write_gmureg(adreno_dev,
+			ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF);
+	adreno_write_gmureg(adreno_dev,
+			ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+			(unsigned int) ~HFI_IRQ_MASK);
 
 	gmu->fault_count++;
 }
diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c
index 3a5b489..daac9f1 100644
--- a/drivers/gpu/msm/kgsl_hfi.c
+++ b/drivers/gpu/msm/kgsl_hfi.c
@@ -611,24 +611,6 @@
 	if (result)
 		return result;
 
-	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) &&
-		test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) {
-		gmu->lm_config.lm_type = 1;
-		gmu->lm_config.lm_sensor_type = 1;
-		gmu->lm_config.throttle_config = 1;
-		gmu->lm_config.idle_throttle_en = 0;
-		gmu->lm_config.acd_en = 0;
-		gmu->bcl_config = 0;
-		gmu->lm_dcvs_level = 0;
-
-		result = hfi_send_lmconfig(gmu);
-		if (result) {
-			dev_err(dev, "Failure enabling LM (%d)\n",
-					result);
-			return result;
-		}
-	}
-
 	/* Tell the GMU we are sending no more HFIs until the next boot */
 	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
 		result = hfi_send_test(gmu);
diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h
index 105599c..b24509d 100644
--- a/drivers/gpu/msm/kgsl_hfi.h
+++ b/drivers/gpu/msm/kgsl_hfi.h
@@ -360,4 +360,5 @@
 		uint32_t bw_idx, enum rpm_ack_type ack_type);
 int hfi_notify_slumber(struct gmu_device *gmu, uint32_t init_perf_idx,
 		uint32_t init_bw_idx);
+int hfi_send_lmconfig(struct gmu_device *gmu);
 #endif  /* __KGSL_HFI_H */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 940a741f..cda7a5b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -2124,6 +2124,45 @@
 		devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk);
 }
 
+static bool _gpu_freq_supported(struct kgsl_pwrctrl *pwr, unsigned int freq)
+{
+	int i;
+
+	for (i = pwr->num_pwrlevels - 2; i >= 0; i--) {
+		if (pwr->pwrlevels[i].gpu_freq == freq)
+			return true;
+	}
+
+	return false;
+}
+
+static void kgsl_pwrctrl_disable_unused_opp(struct kgsl_device *device)
+{
+	struct device *dev = &device->pdev->dev;
+	struct dev_pm_opp *opp;
+	unsigned long freq = 0;
+	int ret;
+
+	ret = dev_pm_opp_get_opp_count(dev);
+	/* Return early, If no OPP table or OPP count is zero */
+	if (ret <= 0)
+		return;
+
+	while (1) {
+		rcu_read_lock();
+		opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+		rcu_read_unlock();
+
+		if (IS_ERR(opp))
+			break;
+
+		if (!_gpu_freq_supported(&device->pwrctrl, freq))
+			dev_pm_opp_disable(dev, freq);
+
+		freq++;
+	}
+}
+
 int kgsl_pwrctrl_init(struct kgsl_device *device)
 {
 	int i, k, m, n = 0, result;
@@ -2181,6 +2220,8 @@
 			pwr->pwrlevels[i].gpu_freq = freq;
 	}
 
+	kgsl_pwrctrl_disable_unused_opp(device);
+
 	kgsl_clk_set_rate(device, pwr->num_pwrlevels - 1);
 
 	clk_set_rate(pwr->grp_clks[6],
@@ -2691,6 +2732,9 @@
 				 * GPU will not be powered on
 				 */
 				WARN_ONCE(1, "Failed to recover GMU\n");
+				device->snapshot->recovered = false;
+			} else {
+				device->snapshot->recovered = true;
 			}
 
 			clear_bit(GMU_FAULT, &gmu->flags);
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index f710d8f..33ce60d 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -663,7 +663,7 @@
 	 * Overwrite a non-GMU fault snapshot if a GMU fault occurs.
 	 */
 	if (device->snapshot != NULL) {
-		if (!gmu_fault || device->snapshot->gmu_fault)
+		if (!gmu_fault || !device->snapshot->recovered)
 			return;
 
 		/*
@@ -689,6 +689,7 @@
 	snapshot->ptr = device->snapshot_memory.ptr;
 	snapshot->remain = device->snapshot_memory.size;
 	snapshot->gmu_fault = gmu_fault;
+	snapshot->recovered = false;
 	snapshot->first_read = true;
 	snapshot->sysfs_read = 0;
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
index 4418fb1..3c572f0 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
@@ -230,7 +230,7 @@
 			.offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */
 			.mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
 			.shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
-			.value = 0,
+			.value = 0x2,
 		},
 		.danger_lut = {
 			.enable = false,
@@ -258,7 +258,7 @@
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.masked_value = 0,
 			.offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */
-			.value = 0x44443333,
+			.value = 0x66666543,
 		},
 		.priority_lut_high = {
 			.enable = true,
@@ -288,7 +288,7 @@
 			.enable = true,
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */
-			.value = 0x3,
+			.value = 0x1,
 		},
 		.ubwc_ctl = {
 			.enable = true,
@@ -306,7 +306,7 @@
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.masked_value = 0,
 			.offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */
-			.value = 0x44443333,
+			.value = 0x66666543,
 		},
 		.priority_lut_high = {
 			.enable = true,
@@ -336,7 +336,7 @@
 			.enable = true,
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */
-			.value = 0x3,
+			.value = 0x1,
 		},
 		.ubwc_ctl = {
 			.enable = true,
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
index ce7a8b3..b9b59a1 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
@@ -123,8 +123,9 @@
  * power collapse for IPE and BPS hardware.
  *
  * @enable: flag to enable/disable
+ * @core_info: Core information to firmware
  */
-int hfi_enable_ipe_bps_pc(bool enable);
+int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info);
 
 /**
  * hfi_cmd_ubwc_config() - UBWC configuration to firmware
@@ -132,4 +133,15 @@
  */
 int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg);
 
+/**
+ * cam_hfi_resume() - function to resume
+ * @hfi_mem: hfi memory info
+ * @icp_base: icp base address
+ * @debug: debug flag
+ *
+ * Returns success(zero)/failure(non zero)
+ */
+int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
+	void __iomem *icp_base, bool debug);
+
 #endif /* _HFI_INTF_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
index eb4b132..6909972 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
@@ -51,6 +51,15 @@
 #define ICP_CSR_DBGSWENABLE                     (1 << 22)
 #define ICP_CSR_A5_STATUS_WFI                   (1 << 7)
 
+#define ICP_FLAG_A5_CTRL_DBG_EN                 (ICP_FLAG_CSR_WAKE_UP_EN|\
+						ICP_FLAG_CSR_A5_EN|\
+						ICP_CSR_EDBGRQ|\
+						ICP_CSR_DBGSWENABLE)
+
+#define ICP_FLAG_A5_CTRL_EN                     (ICP_FLAG_CSR_WAKE_UP_EN|\
+						ICP_FLAG_CSR_A5_EN|\
+						ICP_CSR_EN_CLKGATE_WFI)
+
 /* start of Queue table and queues */
 #define MAX_ICP_HFI_QUEUES                      4
 #define ICP_QHDR_TX_TYPE_MASK                   0xFF000000
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
index aaa18bb..84cc129 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
@@ -254,9 +254,11 @@
  * struct hfi_ipe_bps_pc
  * payload structure to configure HFI_PROPERTY_SYS_IPEBPS_PC
  * @enable: Flag to enable IPE, BPS interfrane power collapse
+ * @core_info: Core information to firmware
  */
 struct hfi_ipe_bps_pc {
 	uint32_t enable;
+	uint32_t core_info;
 } __packed;
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index a8855ae..eca16d6 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -40,6 +40,8 @@
 #define HFI_VERSION_INFO_STEP_BMSK   0xFF
 #define HFI_VERSION_INFO_STEP_SHFT  0
 
+#define HFI_MAX_POLL_TRY 5
+
 static struct hfi_info *g_hfi;
 unsigned int g_icp_mmu_hdl;
 static DEFINE_MUTEX(hfi_cmd_q_mutex);
@@ -248,7 +250,7 @@
 	return 0;
 }
 
-int hfi_enable_ipe_bps_pc(bool enable)
+int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info)
 {
 	uint8_t *prop;
 	struct hfi_cmd_prop *dbg_prop;
@@ -267,6 +269,7 @@
 	dbg_prop->num_prop = 1;
 	dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC;
 	dbg_prop->prop_data[1] = enable;
+	dbg_prop->prop_data[2] = core_info;
 
 	hfi_write_cmd(prop);
 	kfree(prop);
@@ -420,14 +423,28 @@
 {
 	uint32_t data;
 	uint32_t val;
+	uint32_t try = 0;
 
-	data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
-	/* Add waiting logic in case it is not idle */
-	if (data & ICP_CSR_A5_STATUS_WFI) {
-		val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL);
-		val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN);
-		cam_io_w(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL);
+	while (try < HFI_MAX_POLL_TRY) {
+		data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
+		CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);
+
+		if (data & ICP_CSR_A5_STATUS_WFI)
+			break;
+		/* Need to poll here to confirm that FW is going trigger wfi
+		 * and Host can the proceed. No interrupt is expected from FW
+		 * at this time.
+		 */
+		msleep(100);
+		try++;
 	}
+
+	val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL);
+	val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN);
+	cam_io_w(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL);
+
+	val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET);
+	cam_io_w(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
 }
 
 void cam_hfi_enable_cpu(void __iomem *icp_base)
@@ -437,6 +454,64 @@
 	cam_io_w((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
 }
 
+int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
+	void __iomem *icp_base, bool debug)
+{
+	int rc = 0;
+	uint32_t data;
+	uint32_t fw_version, status = 0;
+
+	cam_hfi_enable_cpu(icp_base);
+	g_hfi->csr_base = icp_base;
+
+	rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
+		status, status != ICP_INIT_RESP_SUCCESS, 15, 200);
+
+	if (rc) {
+		CAM_ERR(CAM_HFI, "timed out , status = %u", status);
+		return -EINVAL;
+	}
+
+	fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
+	CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version);
+
+	cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
+
+	if (debug) {
+		cam_io_w_mb(ICP_FLAG_A5_CTRL_DBG_EN,
+			(icp_base + HFI_REG_A5_CSR_A5_CONTROL));
+
+		/* Barrier needed as next write should be done after
+		 * sucessful previous write. Next write enable clock
+		 * gating
+		 */
+		wmb();
+
+		cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN,
+			icp_base + HFI_REG_A5_CSR_A5_CONTROL);
+
+	} else {
+		cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN,
+			icp_base + HFI_REG_A5_CSR_A5_CONTROL);
+	}
+
+	data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
+	CAM_DBG(CAM_HFI, "wfi status = %x", (int)data);
+
+	cam_io_w((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
+	cam_io_w((uint32_t)hfi_mem->shmem.iova,
+		icp_base + HFI_REG_SHARED_MEM_PTR);
+	cam_io_w((uint32_t)hfi_mem->shmem.len,
+		icp_base + HFI_REG_SHARED_MEM_SIZE);
+	cam_io_w((uint32_t)hfi_mem->sec_heap.iova,
+		icp_base + HFI_REG_UNCACHED_HEAP_PTR);
+	cam_io_w((uint32_t)hfi_mem->sec_heap.len,
+		icp_base + HFI_REG_UNCACHED_HEAP_SIZE);
+
+	cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
+	return rc;
+}
+
 int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
 		void __iomem *icp_base, bool debug)
 {
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
index 635d0df..aeec16c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
@@ -422,6 +422,11 @@
 	case CAM_ICP_A5_SEND_INIT:
 		hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0);
 		break;
+
+	case CAM_ICP_A5_CMD_PC_PREP:
+		hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0);
+		break;
+
 	case CAM_ICP_A5_CMD_VOTE_CPAS: {
 		struct cam_icp_cpas_vote *cpas_vote = cmd_args;
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
index 3473d08..c18a5e4 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
@@ -157,8 +157,11 @@
 			CAM_CPAS_REG_CPASTOP,
 			hw_info->pwr_ctrl, true, 0x1);
 
-		if ((pwr_status >> BPS_PWR_ON_MASK))
+		if ((pwr_status >> BPS_PWR_ON_MASK)) {
+			CAM_ERR(CAM_ICP, "BPS: pwr_status(%x):pwr_ctrl(%x)",
+				pwr_status, pwr_ctrl);
 			return -EINVAL;
+		}
 	}
 	cam_bps_get_gdsc_control(soc_info);
 	cam_cpas_reg_read(core_info->cpas_handle,
@@ -189,7 +192,7 @@
 	cam_cpas_reg_read(core_info->cpas_handle,
 		CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
 	if (pwr_ctrl & BPS_COLLAPSE_MASK) {
-		CAM_ERR(CAM_ICP, "BPS: resume failed : %d", pwr_ctrl);
+		CAM_ERR(CAM_ICP, "BPS: pwr_ctrl(%x)", pwr_ctrl);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 6f997a2..29a1b9a 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -729,9 +729,6 @@
 	struct cam_hw_intf *bps_dev_intf = NULL;
 	int rc = 0;
 
-	if (!icp_hw_mgr.icp_pc_flag)
-		return rc;
-
 	ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
 	ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
 	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
@@ -741,36 +738,61 @@
 		return -EINVAL;
 	}
 
-	bps_dev_intf->hw_ops.process_cmd(
-		bps_dev_intf->hw_priv,
-		CAM_ICP_BPS_CMD_POWER_RESUME, NULL, 0);
+	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
+		if (hw_mgr->bps_ctxt_cnt++)
+			goto end;
+		bps_dev_intf->hw_ops.init(bps_dev_intf->hw_priv, NULL, 0);
+		if (icp_hw_mgr.icp_pc_flag) {
+			bps_dev_intf->hw_ops.process_cmd(
+				bps_dev_intf->hw_priv,
+				CAM_ICP_BPS_CMD_POWER_RESUME, NULL, 0);
+			hw_mgr->core_info = hw_mgr->core_info | ICP_PWR_CLP_BPS;
+		}
+	} else {
+		if (hw_mgr->ipe_ctxt_cnt++)
+			goto end;
 
-	ipe0_dev_intf->hw_ops.process_cmd(
-		ipe0_dev_intf->hw_priv,
-		CAM_ICP_IPE_CMD_POWER_RESUME, NULL, 0);
+		ipe0_dev_intf->hw_ops.init(ipe0_dev_intf->hw_priv, NULL, 0);
+		if (icp_hw_mgr.icp_pc_flag) {
+			ipe0_dev_intf->hw_ops.process_cmd(
+				ipe0_dev_intf->hw_priv,
+				CAM_ICP_IPE_CMD_POWER_RESUME, NULL, 0);
+		}
 
-	if (ipe1_dev_intf) {
-		ipe1_dev_intf->hw_ops.process_cmd(
-			ipe1_dev_intf->hw_priv,
-			CAM_ICP_IPE_CMD_POWER_RESUME, NULL, 0);
+		if ((icp_hw_mgr.ipe1_enable) && (ipe1_dev_intf)) {
+			ipe1_dev_intf->hw_ops.init(ipe1_dev_intf->hw_priv,
+				NULL, 0);
+
+			if (icp_hw_mgr.icp_pc_flag) {
+				ipe1_dev_intf->hw_ops.process_cmd(
+					ipe1_dev_intf->hw_priv,
+					CAM_ICP_IPE_CMD_POWER_RESUME,
+					NULL, 0);
+			}
+		}
+		if (icp_hw_mgr.icp_pc_flag) {
+			hw_mgr->core_info = hw_mgr->core_info |
+				(ICP_PWR_CLP_IPE0 | ICP_PWR_CLP_IPE1);
+		}
 	}
 
-	rc = hfi_enable_ipe_bps_pc(true);
-
+	CAM_DBG(CAM_ICP, "core_info %X",  hw_mgr->core_info);
+	if (icp_hw_mgr.icp_pc_flag)
+		rc = hfi_enable_ipe_bps_pc(true, hw_mgr->core_info);
+	else
+		rc = hfi_enable_ipe_bps_pc(false, hw_mgr->core_info);
+end:
 	return rc;
 }
 
 static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr,
 	struct cam_icp_hw_ctx_data *ctx_data, int dev_type)
 {
-	int rc = 0;
+	int rc = 0, dev;
 	struct cam_hw_intf *ipe0_dev_intf = NULL;
 	struct cam_hw_intf *ipe1_dev_intf = NULL;
 	struct cam_hw_intf *bps_dev_intf = NULL;
 
-	if (!icp_hw_mgr.icp_pc_flag)
-		return rc;
-
 	ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
 	ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
 	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
@@ -780,20 +802,64 @@
 		return -EINVAL;
 	}
 
-	rc = bps_dev_intf->hw_ops.process_cmd(
-		bps_dev_intf->hw_priv,
-		CAM_ICP_BPS_CMD_POWER_COLLAPSE, NULL, 0);
+	if (!ctx_data)
+		dev = dev_type;
+	else
+		dev = ctx_data->icp_dev_acquire_info->dev_type;
 
-	rc = ipe0_dev_intf->hw_ops.process_cmd(
-		ipe0_dev_intf->hw_priv,
-		CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0);
+	if (dev == CAM_ICP_RES_TYPE_BPS) {
+		CAM_DBG(CAM_ICP, "bps ctx cnt %d", hw_mgr->bps_ctxt_cnt);
+		if (ctx_data)
+			--hw_mgr->bps_ctxt_cnt;
 
-	if (ipe1_dev_intf) {
-		rc = ipe1_dev_intf->hw_ops.process_cmd(
-			ipe1_dev_intf->hw_priv,
-			CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0);
+		if (hw_mgr->bps_ctxt_cnt)
+			goto end;
+
+		if (icp_hw_mgr.icp_pc_flag) {
+			rc = bps_dev_intf->hw_ops.process_cmd(
+				bps_dev_intf->hw_priv,
+				CAM_ICP_BPS_CMD_POWER_COLLAPSE,
+				NULL, 0);
+			hw_mgr->core_info =
+				hw_mgr->core_info & (~ICP_PWR_CLP_BPS);
+		}
+
+		bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0);
+	} else {
+		CAM_DBG(CAM_ICP, "ipe ctx cnt %d", hw_mgr->ipe_ctxt_cnt);
+		if (ctx_data)
+			--hw_mgr->ipe_ctxt_cnt;
+
+		if (hw_mgr->ipe_ctxt_cnt)
+			goto end;
+
+		if (icp_hw_mgr.icp_pc_flag) {
+			rc = ipe0_dev_intf->hw_ops.process_cmd(
+				ipe0_dev_intf->hw_priv,
+				CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0);
+
+		}
+		ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0);
+
+		if (ipe1_dev_intf) {
+			if (icp_hw_mgr.icp_pc_flag) {
+				rc = ipe1_dev_intf->hw_ops.process_cmd(
+					ipe1_dev_intf->hw_priv,
+					CAM_ICP_IPE_CMD_POWER_COLLAPSE,
+					NULL, 0);
+			}
+
+			ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv,
+				NULL, 0);
+		}
+		if (icp_hw_mgr.icp_pc_flag) {
+			hw_mgr->core_info = hw_mgr->core_info &
+				(~(ICP_PWR_CLP_IPE0 | ICP_PWR_CLP_IPE1));
+		}
 	}
 
+	CAM_DBG(CAM_ICP, "Exit: core_info = %x", hw_mgr->core_info);
+end:
 	return rc;
 }
 
@@ -844,6 +910,7 @@
 		rc = -ENOMEM;
 		goto err;
 	}
+	icp_hw_mgr.icp_pc_flag = 1;
 
 	if (!debugfs_create_file("icp_debug_clk",
 		0644,
@@ -1229,13 +1296,19 @@
 {
 	int rc = 0;
 	int size_processed = 0;
-	struct hfi_msg_ipebps_async_ack *async_ack = NULL;
 
 	switch (msg_ptr[ICP_PACKET_TYPE]) {
 	case HFI_MSG_SYS_INIT_DONE:
 		CAM_DBG(CAM_ICP, "received SYS_INIT_DONE");
 		complete(&hw_mgr->a5_complete);
-		size_processed = sizeof(struct hfi_msg_init_done);
+		size_processed = (
+			(struct hfi_msg_init_done *)msg_ptr)->size;
+		break;
+
+	case HFI_MSG_SYS_PC_PREP_DONE:
+		CAM_DBG(CAM_ICP, "HFI_MSG_SYS_PC_PREP_DONE is received\n");
+		complete(&hw_mgr->a5_complete);
+		size_processed = sizeof(struct hfi_msg_pc_prep_done);
 		break;
 
 	case HFI_MSG_SYS_PING_ACK:
@@ -1253,20 +1326,21 @@
 	case HFI_MSG_IPEBPS_ASYNC_COMMAND_INDIRECT_ACK:
 		CAM_DBG(CAM_ICP, "received ASYNC_INDIRECT_ACK");
 		rc = cam_icp_mgr_process_indirect_ack_msg(msg_ptr);
-		async_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
-		size_processed = async_ack->size;
-		async_ack = NULL;
+		size_processed = (
+			(struct hfi_msg_ipebps_async_ack *)msg_ptr)->size;
 		break;
 
 	case  HFI_MSG_IPEBPS_ASYNC_COMMAND_DIRECT_ACK:
 		CAM_DBG(CAM_ICP, "received ASYNC_DIRECT_ACK");
 		rc = cam_icp_mgr_process_direct_ack_msg(msg_ptr);
-		size_processed = sizeof(struct hfi_msg_ipebps_async_ack);
+		size_processed = (
+			(struct hfi_msg_ipebps_async_ack *)msg_ptr)->size;
 		break;
 
 	case HFI_MSG_EVENT_NOTIFY:
 		CAM_DBG(CAM_ICP, "received EVENT_NOTIFY");
-		size_processed = sizeof(struct hfi_msg_event_notify);
+		size_processed = (
+			(struct hfi_msg_event_notify *)msg_ptr)->size;
 		break;
 
 	default:
@@ -1357,13 +1431,13 @@
 {
 	int rc;
 	cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl);
+	rc = cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap);
+	if (rc)
+		CAM_ERR(CAM_ICP, "failed to unreserve sec heap");
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.qtbl);
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.cmd_q);
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.msg_q);
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.dbg_q);
-	rc = cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap);
-	if (rc)
-		CAM_ERR(CAM_ICP, "failed to unreserve sec heap");
 }
 
 static int cam_icp_alloc_secheap_mem(struct cam_mem_mgr_memory_desc *secheap)
@@ -1534,6 +1608,159 @@
 	ctx_data->state = CAM_ICP_CTX_STATE_FREE;
 }
 
+static int cam_icp_mgr_send_pc_prep(struct cam_icp_hw_mgr *hw_mgr)
+{
+	int rc;
+	struct cam_hw_intf *a5_dev_intf = NULL;
+	unsigned long rem_jiffies;
+	int timeout = 5000;
+
+	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
+	if (!a5_dev_intf) {
+		CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n");
+		return -EINVAL;
+	}
+
+	reinit_completion(&hw_mgr->a5_complete);
+	CAM_DBG(CAM_ICP, "Sending HFI init command");
+	rc = a5_dev_intf->hw_ops.process_cmd(
+		a5_dev_intf->hw_priv, CAM_ICP_A5_CMD_PC_PREP, NULL, 0);
+	if (rc)
+		return rc;
+
+	CAM_DBG(CAM_ICP, "Wait for PC_PREP_DONE Message\n");
+	rem_jiffies = wait_for_completion_timeout(&icp_hw_mgr.a5_complete,
+		msecs_to_jiffies((timeout)));
+	if (!rem_jiffies) {
+		rc = -ETIMEDOUT;
+		CAM_ERR(CAM_ICP, "PC_PREP response timed out %d\n", rc);
+	}
+	CAM_DBG(CAM_ICP, "Done Waiting for PC_PREP Message\n");
+
+	return rc;
+}
+
+static int cam_ipe_bps_deint(struct cam_icp_hw_mgr *hw_mgr)
+{
+	struct cam_hw_intf *ipe0_dev_intf = NULL;
+	struct cam_hw_intf *ipe1_dev_intf = NULL;
+	struct cam_hw_intf *bps_dev_intf = NULL;
+
+	ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
+	ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
+	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
+	if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
+		CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to close");
+		return 0;
+	}
+
+	if (ipe1_dev_intf) {
+		ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv,
+				NULL, 0);
+	}
+	ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0);
+	bps_dev_intf->hw_ops.deinit(bps_dev_intf->hw_priv, NULL, 0);
+	return 0;
+}
+static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr)
+{
+	int rc;
+	struct cam_hw_intf *a5_dev_intf = NULL;
+	struct cam_hw_info *a5_dev = NULL;
+
+	CAM_DBG(CAM_ICP, "ENTER");
+
+	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
+	if (!a5_dev_intf) {
+		CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n");
+		return -EINVAL;
+	}
+	a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
+
+	rc = cam_icp_mgr_send_pc_prep(hw_mgr);
+
+	cam_hfi_disable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
+	a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0);
+	CAM_DBG(CAM_ICP, "EXIT");
+
+	return rc;
+}
+
+static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
+{
+	struct cam_hw_intf *a5_dev_intf = NULL;
+	struct cam_hw_info *a5_dev = NULL;
+	struct hfi_mem_info hfi_mem;
+
+	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
+	if (!a5_dev_intf) {
+		CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n");
+		return -EINVAL;
+	}
+	a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
+
+	hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva;
+	hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova;
+	hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len;
+	 CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+		hfi_mem.qtbl.kva, hfi_mem.qtbl.iova, hfi_mem.qtbl.len);
+
+	hfi_mem.cmd_q.kva = icp_hw_mgr.hfi_mem.cmd_q.kva;
+	hfi_mem.cmd_q.iova = icp_hw_mgr.hfi_mem.cmd_q.iova;
+	hfi_mem.cmd_q.len = icp_hw_mgr.hfi_mem.cmd_q.len;
+	CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+		hfi_mem.cmd_q.kva, hfi_mem.cmd_q.iova, hfi_mem.cmd_q.len);
+
+	hfi_mem.msg_q.kva = icp_hw_mgr.hfi_mem.msg_q.kva;
+	hfi_mem.msg_q.iova = icp_hw_mgr.hfi_mem.msg_q.iova;
+	hfi_mem.msg_q.len = icp_hw_mgr.hfi_mem.msg_q.len;
+	CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+		hfi_mem.msg_q.kva, hfi_mem.msg_q.iova, hfi_mem.msg_q.len);
+
+	hfi_mem.dbg_q.kva = icp_hw_mgr.hfi_mem.dbg_q.kva;
+	hfi_mem.dbg_q.iova = icp_hw_mgr.hfi_mem.dbg_q.iova;
+	hfi_mem.dbg_q.len = icp_hw_mgr.hfi_mem.dbg_q.len;
+	CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+		hfi_mem.dbg_q.kva, hfi_mem.dbg_q.iova, hfi_mem.dbg_q.len);
+
+	hfi_mem.sec_heap.kva = icp_hw_mgr.hfi_mem.sec_heap.kva;
+	hfi_mem.sec_heap.iova = icp_hw_mgr.hfi_mem.sec_heap.iova;
+	hfi_mem.sec_heap.len = icp_hw_mgr.hfi_mem.sec_heap.len;
+
+	hfi_mem.shmem.iova = icp_hw_mgr.hfi_mem.shmem.iova_start;
+	hfi_mem.shmem.len = icp_hw_mgr.hfi_mem.shmem.iova_len;
+	return cam_hfi_resume(&hfi_mem,
+		a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
+		hw_mgr->a5_jtag_debug);
+}
+
+static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr)
+{
+	int rc = 0;
+	struct cam_hw_intf *a5_dev_intf = NULL;
+
+	CAM_DBG(CAM_ICP, "Enter");
+	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
+
+	if (!a5_dev_intf) {
+		CAM_ERR(CAM_ICP, "a5 dev intf is wrong");
+		return -EINVAL;
+	}
+
+	rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0);
+	if (rc)
+		return -EINVAL;
+
+	rc = cam_icp_mgr_hfi_resume(hw_mgr);
+	if (rc)
+		goto hfi_resume_failed;
+
+	CAM_DBG(CAM_ICP, "Exit");
+	return rc;
+hfi_resume_failed:
+	cam_icp_mgr_icp_power_collapse(hw_mgr);
+	return rc;
+}
 static int cam_icp_mgr_abort_handle(
 	struct cam_icp_hw_ctx_data *ctx_data)
 {
@@ -1673,13 +1900,12 @@
 		return -EINVAL;
 	}
 
-	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
 	if (hw_mgr->ctx_data[ctx_id].state !=
 		CAM_ICP_CTX_STATE_ACQUIRED) {
 		mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
-		CAM_WARN(CAM_ICP,
+		CAM_DBG(CAM_ICP,
 			"ctx with id: %d not in right state to release: %d",
 			ctx_id, hw_mgr->ctx_data[ctx_id].state);
 		return 0;
@@ -1704,7 +1930,6 @@
 	hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
 	hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_FREE;
 	mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
-	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
 	return 0;
 }
@@ -1739,10 +1964,11 @@
 	struct cam_hw_intf *a5_dev_intf = NULL;
 	struct cam_icp_a5_set_irq_cb irq_cb;
 	struct cam_icp_a5_set_fw_buf_info fw_buf_info;
-	int i, rc = 0;
+	int rc = 0;
 
+	CAM_DBG(CAM_ICP, "E");
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
-	if ((hw_mgr->fw_download ==  false) && (!hw_mgr->ctxt_cnt)) {
+	if (hw_mgr->fw_download == false) {
 		CAM_DBG(CAM_ICP, "hw mgr is already closed");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		return 0;
@@ -1750,7 +1976,7 @@
 
 	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];
 	if (!a5_dev_intf) {
-		CAM_ERR(CAM_ICP, "a5_dev_intf is NULL");
+		CAM_DBG(CAM_ICP, "a5_dev_intf is NULL");
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		return -EINVAL;
 	}
@@ -1765,14 +1991,8 @@
 		sizeof(fw_buf_info));
 	if (rc)
 		CAM_ERR(CAM_ICP, "nullify the fw buf failed");
-	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
-	for (i = 0; i < CAM_ICP_CTX_MAX; i++)
-		cam_icp_mgr_release_ctx(hw_mgr, i);
-
-	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	cam_hfi_deinit();
-	cam_icp_mgr_device_deinit(hw_mgr);
 
 	irq_cb.icp_hw_mgr_cb = NULL;
 	irq_cb.data = NULL;
@@ -2020,21 +2240,18 @@
 		goto fw_init_failed;
 	}
 
-	rc = a5_dev_intf->hw_ops.process_cmd(
-		a5_dev_intf->hw_priv,
-		CAM_ICP_A5_CMD_POWER_COLLAPSE,
-		NULL, 0);
-	hw_mgr->fw_download = true;
 	hw_mgr->ctxt_cnt = 0;
-	CAM_DBG(CAM_ICP, "FW download done successfully");
 
 	if (icp_hw_mgr.a5_debug_q)
 		hfi_set_debug_level(icp_hw_mgr.a5_dbg_lvl);
 
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
-	if (!download_fw_args)
-		cam_icp_mgr_hw_close(hw_mgr, NULL);
 
+	rc = cam_ipe_bps_deint(hw_mgr);
+	rc = cam_icp_mgr_icp_power_collapse(hw_mgr);
+
+	hw_mgr->fw_download = true;
+	CAM_DBG(CAM_ICP, "FW download done successfully");
 	return rc;
 
 fw_init_failed:
@@ -2504,7 +2721,7 @@
 
 	ctx_data = release_hw->ctxt_to_hw_map;
 	if (!ctx_data) {
-		CAM_ERR(CAM_ICP, "NULL ctx");
+		CAM_ERR(CAM_ICP, "NULL ctx data");
 		return -EINVAL;
 	}
 
@@ -2527,14 +2744,15 @@
 		cam_icp_mgr_send_abort_status(ctx_data);
 	}
 
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	rc = cam_icp_mgr_release_ctx(hw_mgr, ctx_id);
 	if (!hw_mgr->ctxt_cnt) {
-		cam_icp_mgr_ipe_bps_power_collapse(hw_mgr,
-			NULL, 0);
-		cam_icp_mgr_hw_close(hw_mgr, NULL);
+		CAM_DBG(CAM_ICP, "Last Release");
+		cam_icp_mgr_icp_power_collapse(hw_mgr);
 		cam_icp_hw_mgr_reset_clk_info(hw_mgr);
 		hw_mgr->secure_mode = CAM_SECURE_MODE_NON_SECURE;
 	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
 	return rc;
 }
@@ -2676,8 +2894,10 @@
 
 	if (copy_from_user(&icp_dev_acquire_info,
 		(void __user *)args->acquire_info,
-		sizeof(struct cam_icp_acquire_dev_info)))
+		sizeof(struct cam_icp_acquire_dev_info))) {
+		CAM_ERR(CAM_ICP, "Failed in acquire");
 		return -EFAULT;
+	}
 
 	if (icp_dev_acquire_info.secure_mode > CAM_SECURE_MODE_SECURE) {
 		CAM_ERR(CAM_ICP, "Invalid mode:%d",
@@ -2710,7 +2930,7 @@
 	}
 
 	acquire_size = sizeof(struct cam_icp_acquire_dev_info) +
-		(icp_dev_acquire_info.num_out_res *
+		((icp_dev_acquire_info.num_out_res - 1) *
 		sizeof(struct cam_icp_res_info));
 	ctx_data->icp_dev_acquire_info = kzalloc(acquire_size, GFP_KERNEL);
 	if (!ctx_data->icp_dev_acquire_info) {
@@ -2721,6 +2941,7 @@
 
 	if (copy_from_user(ctx_data->icp_dev_acquire_info,
 		(void __user *)args->acquire_info, acquire_size)) {
+		CAM_ERR(CAM_ICP, "Failed in acquire: size = %d", acquire_size);
 		if (!hw_mgr->ctxt_cnt)
 			hw_mgr->secure_mode = CAM_SECURE_MODE_NON_SECURE;
 		kfree(ctx_data->icp_dev_acquire_info);
@@ -2804,21 +3025,28 @@
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	if (!hw_mgr->ctxt_cnt) {
-		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		rc = cam_icp_clk_info_init(hw_mgr, ctx_data);
-		if (rc)
+		if (rc) {
+			mutex_unlock(&hw_mgr->hw_mgr_mutex);
 			goto get_io_buf_failed;
-		rc = cam_icp_mgr_hw_open(hw_mgr, ctx_data);
-		if (rc)
+		}
+
+		rc = cam_icp_mgr_icp_resume(hw_mgr);
+		if (rc) {
+			mutex_unlock(&hw_mgr->hw_mgr_mutex);
 			goto get_io_buf_failed;
-		rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data);
-		if (rc)
-			goto ipe_bps_resume_failed;
+		}
 
 		rc = cam_icp_send_ubwc_cfg(hw_mgr);
-		if (rc)
+		if (rc) {
+			mutex_unlock(&hw_mgr->hw_mgr_mutex);
 			goto ubwc_cfg_failed;
-		mutex_lock(&hw_mgr->hw_mgr_mutex);
+		}
+	}
+	rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data);
+	if (rc) {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		goto ipe_bps_resume_failed;
 	}
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
@@ -2827,6 +3055,7 @@
 		CAM_ERR(CAM_ICP, "ping ack not received");
 		goto send_ping_failed;
 	}
+	CAM_DBG(CAM_ICP, "ping ack received");
 
 	rc = cam_icp_mgr_create_handle(icp_dev_acquire_info->dev_type,
 		ctx_data);
@@ -2866,6 +3095,7 @@
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	hw_mgr->ctxt_cnt++;
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	CAM_DBG(CAM_ICP, "Acquire Done");
 
 	return 0;
 
@@ -2876,11 +3106,11 @@
 	cam_icp_mgr_destroy_handle(ctx_data);
 create_handle_failed:
 send_ping_failed:
-ubwc_cfg_failed:
 	cam_icp_mgr_ipe_bps_power_collapse(hw_mgr, ctx_data, 0);
 ipe_bps_resume_failed:
+ubwc_cfg_failed:
 	if (!hw_mgr->ctxt_cnt)
-		cam_icp_mgr_hw_close(hw_mgr, NULL);
+		cam_icp_mgr_icp_power_collapse(hw_mgr);
 get_io_buf_failed:
 	kfree(hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info);
 	hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index ab19f45..e8919e8 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -252,6 +252,7 @@
  * @ipe0_enable: Flag for IPE0
  * @ipe1_enable: Flag for IPE1
  * @bps_enable: Flag for BPS
+ * @core_info: 32 bit value , tells IPE0/1 and BPS
  */
 struct cam_icp_hw_mgr {
 	struct mutex hw_mgr_mutex;
@@ -288,9 +289,11 @@
 	bool ipe0_enable;
 	bool ipe1_enable;
 	bool bps_enable;
+	uint32_t core_info;
 };
 
 static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args);
 static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args);
-
+static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr);
+static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr);
 #endif /* CAM_ICP_HW_MGR_H */
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h
index dad7736..fd0482c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h
@@ -32,6 +32,7 @@
 	CAM_ICP_A5_CMD_CPAS_START,
 	CAM_ICP_A5_CMD_CPAS_STOP,
 	CAM_ICP_A5_CMD_UBWC_CFG,
+	CAM_ICP_A5_CMD_PC_PREP,
 	CAM_ICP_A5_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 9bdde9c..ccab3a0 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1986,6 +1986,7 @@
 	struct cam_hw_release_args       *release_args = release_hw_args;
 	struct cam_ife_hw_mgr            *hw_mgr       = hw_mgr_priv;
 	struct cam_ife_hw_mgr_ctx        *ctx;
+	uint32_t                          i;
 
 	if (!hw_mgr_priv || !release_hw_args) {
 		CAM_ERR(CAM_ISP, "Invalid arguments");
@@ -2015,6 +2016,14 @@
 	list_del_init(&ctx->list);
 	ctx->ctx_in_use = 0;
 	ctx->is_rdi_only_context = 0;
+	ctx->cdm_handle = 0;
+	ctx->cdm_ops = NULL;
+	atomic_set(&ctx->overflow_pending, 0);
+	for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
+		ctx->sof_cnt[i] = 0;
+		ctx->eof_cnt[i] = 0;
+		ctx->epoch_cnt[i] = 0;
+	}
 	CAM_DBG(CAM_ISP, "Exit...ctx id:%d",
 		ctx->ctx_index);
 	cam_ife_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index 4bee732..031b7b2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -316,14 +316,15 @@
 		cam_io_w_mb(irq_mask, controller->mem_base +
 			controller->irq_register_arr[i].mask_reg_offset);
 	}
-	if (need_lock)
-		spin_unlock_irqrestore(&controller->lock, flags);
 
 	list_add_tail(&evt_handler->list_node,
 		&controller->evt_handler_list_head);
 	list_add_tail(&evt_handler->th_list_node,
 		&controller->th_list_head[priority]);
 
+	if (need_lock)
+		spin_unlock_irqrestore(&controller->lock, flags);
+
 	return evt_handler->index;
 
 free_evt_handler:
@@ -348,6 +349,10 @@
 	if (!controller)
 		return rc;
 
+	need_lock = !in_irq();
+	if (need_lock)
+		spin_lock_irqsave(&controller->lock, flags);
+
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
@@ -358,12 +363,12 @@
 		}
 	}
 
-	if (!found)
+	if (!found) {
+		if (need_lock)
+			spin_unlock_irqrestore(&controller->lock, flags);
 		return rc;
+	}
 
-	need_lock = !in_irq();
-	if (need_lock)
-		spin_lock_irqsave(&controller->lock, flags);
 	for (i = 0; i < controller->num_registers; i++) {
 		controller->irq_register_arr[i].
 		top_half_enable_mask[evt_handler->priority] |=
@@ -398,6 +403,10 @@
 	if (!controller)
 		return rc;
 
+	need_lock = !in_irq();
+	if (need_lock)
+		spin_lock_irqsave(&controller->lock, flags);
+
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
@@ -408,12 +417,12 @@
 		}
 	}
 
-	if (!found)
+	if (!found) {
+		if (need_lock)
+			spin_unlock_irqrestore(&controller->lock, flags);
 		return rc;
+	}
 
-	need_lock = !in_irq();
-	if (need_lock)
-		spin_lock_irqsave(&controller->lock, flags);
 	for (i = 0; i < controller->num_registers; i++) {
 		controller->irq_register_arr[i].
 		top_half_enable_mask[evt_handler->priority] &=
@@ -459,6 +468,10 @@
 	int                         rc = -EINVAL;
 	bool                        need_lock;
 
+	need_lock = !in_irq();
+	if (need_lock)
+		spin_lock_irqsave(&controller->lock, flags);
+
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
@@ -471,11 +484,7 @@
 		}
 	}
 
-	need_lock = !in_irq();
-
 	if (found) {
-		if (need_lock)
-			spin_lock_irqsave(&controller->lock, flags);
 		for (i = 0; i < controller->num_registers; i++) {
 			controller->irq_register_arr[i].
 				top_half_enable_mask[evt_handler->priority] &=
@@ -501,13 +510,14 @@
 					controller->mem_base +
 					controller->global_clear_offset);
 		}
-		if (need_lock)
-			spin_unlock_irqrestore(&controller->lock, flags);
 
 		kfree(evt_handler->evt_bit_mask_arr);
 		kfree(evt_handler);
 	}
 
+	if (need_lock)
+		spin_unlock_irqrestore(&controller->lock, flags);
+
 	return rc;
 }
 
@@ -630,8 +640,6 @@
 					i, j, need_th_processing[j]);
 		}
 	}
-	CAM_DBG(CAM_ISP, "unlocked controller %pK name %s lock %pK",
-		controller, controller->name, &controller->lock);
 
 	CAM_DBG(CAM_ISP, "Status Registers read Successful");
 
@@ -649,6 +657,8 @@
 		}
 	}
 	spin_unlock(&controller->lock);
+	CAM_DBG(CAM_ISP, "unlocked controller %pK name %s lock %pK",
+		controller, controller->name, &controller->lock);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 4a7eb00..70c9c3b 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1497,9 +1497,9 @@
 	struct cam_isp_resource_node    *res)
 {
 	int rc = 0;
+	uint32_t val = 0;
 	struct cam_ife_csid_reg_offset      *csid_reg;
 	struct cam_hw_soc_info              *soc_info;
-	uint32_t val = 0;
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
@@ -1596,10 +1596,10 @@
 	enum cam_ife_csid_halt_cmd       stop_cmd)
 {
 	int rc = 0;
+	uint32_t val = 0;
 	struct cam_ife_csid_reg_offset       *csid_reg;
 	struct cam_hw_soc_info               *soc_info;
 	struct cam_ife_csid_path_cfg         *path_data;
-	uint32_t val = 0;
 
 	path_data = (struct cam_ife_csid_path_cfg   *) res->res_priv;
 	csid_reg = csid_hw->csid_info->csid_reg;
@@ -1656,21 +1656,6 @@
 
 	/* For slave mode, halt command should take it from master */
 
-	/* Enable the EOF interrupt for resume at boundary case */
-	if (stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
-		init_completion(&csid_hw->csid_ipp_complete);
-		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-				csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
-		val |= CSID_PATH_INFO_INPUT_EOF;
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
-	} else {
-		val &= ~(CSID_PATH_INFO_RST_DONE |
-			CSID_PATH_ERROR_FIFO_OVERFLOW);
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
-	}
-
 	return rc;
 }
 
@@ -1811,9 +1796,9 @@
 	struct cam_isp_resource_node    *res)
 {
 	int rc = 0;
+	uint32_t val = 0, id;
 	struct cam_ife_csid_reg_offset      *csid_reg;
 	struct cam_hw_soc_info              *soc_info;
-	uint32_t val = 0, id;
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
@@ -1889,9 +1874,9 @@
 	enum cam_ife_csid_halt_cmd                stop_cmd)
 {
 	int rc = 0;
+	uint32_t id;
 	struct cam_ife_csid_reg_offset       *csid_reg;
 	struct cam_hw_soc_info               *soc_info;
-	uint32_t  val = 0, id;
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
@@ -1926,25 +1911,9 @@
 		return -EINVAL;
 	}
 
-
 	CAM_DBG(CAM_ISP, "CSID:%d res_id:%d",
 		csid_hw->hw_intf->hw_idx, res->res_id);
 
-	init_completion(&csid_hw->csid_rdin_complete[id]);
-
-	if (stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
-		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
-		val |= CSID_PATH_INFO_INPUT_EOF;
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
-	} else {
-		val &= ~(CSID_PATH_INFO_RST_DONE |
-				CSID_PATH_ERROR_FIFO_OVERFLOW);
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
-	}
-
 	/*Halt the RDI path */
 	cam_io_w_mb(stop_cmd, soc_info->reg_map[0].mem_base +
 			csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
@@ -2029,12 +1998,10 @@
 	struct cam_isp_resource_node    *res)
 {
 	int rc = 0;
+	uint32_t val = 0, id, status, path_status_reg;
 	struct cam_ife_csid_reg_offset      *csid_reg;
 	struct cam_hw_soc_info              *soc_info;
 
-	struct completion  *complete;
-	uint32_t val = 0, id;
-
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
 
@@ -2060,19 +2027,19 @@
 	}
 
 	if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP)
-		complete = &csid_hw->csid_ipp_complete;
+		path_status_reg = csid_reg->ipp_reg->csid_ipp_status_addr;
 	else
-		complete =  &csid_hw->csid_rdin_complete[res->res_id];
+		path_status_reg = csid_reg->rdi_reg[res->res_id]->
+			csid_rdi_status_addr;
 
-	rc = wait_for_completion_timeout(complete,
-		msecs_to_jiffies(IFE_CSID_TIMEOUT));
-	if (rc <= 0) {
-		CAM_ERR(CAM_ISP, "CSID%d stop at frame boundary failid:%drc:%d",
-			 csid_hw->hw_intf->hw_idx,
-			res->res_id, rc);
-		if (rc == 0)
-			/* continue even have timeout */
-			rc = -ETIMEDOUT;
+	rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
+		path_status_reg, status,
+		(status == 1),
+		CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
+	if (rc < 0) {
+		CAM_ERR(CAM_ISP, "Time out: Res id:%d Path has not halted",
+			res->res_id);
+		rc = -ETIMEDOUT;
 	}
 
 	/* Disable the interrupt */
@@ -2813,9 +2780,6 @@
 			CAM_ERR(CAM_ISP, "CSID:%d IPP EOF received",
 				csid_hw->hw_intf->hw_idx);
 
-		if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOF)
-			complete(&csid_hw->csid_ipp_complete);
-
 		if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
 			CAM_ERR(CAM_ISP, "CSID:%d IPP fifo over flow",
 				csid_hw->hw_intf->hw_idx);
@@ -2841,9 +2805,6 @@
 			(csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ))
 			CAM_ERR(CAM_ISP, "CSID RDI:%d EOF received", i);
 
-		if (irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF)
-			complete(&csid_hw->csid_rdin_complete[i]);
-
 		if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
 			CAM_ERR(CAM_ISP, "CSID:%d RDI fifo over flow",
 				csid_hw->hw_intf->hw_idx);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index 6ad0934..9689698 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -768,7 +768,10 @@
 		}
 
 		mutex_lock(&tbl.bufq[i].q_lock);
-		ion_free(tbl.client, tbl.bufq[i].i_hdl);
+		if (tbl.bufq[i].i_hdl) {
+			ion_free(tbl.client, tbl.bufq[i].i_hdl);
+			tbl.bufq[i].i_hdl = NULL;
+		}
 		tbl.bufq[i].fd = -1;
 		tbl.bufq[i].flags = 0;
 		tbl.bufq[i].buf_handle = -1;
@@ -813,7 +816,17 @@
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_CRM, "Flags = %X", tbl.bufq[idx].flags);
+	CAM_DBG(CAM_CRM, "Flags = %X idx %d", tbl.bufq[idx].flags, idx);
+
+	mutex_lock(&tbl.m_lock);
+	if ((!tbl.bufq[idx].active) &&
+		(tbl.bufq[idx].vaddr) == 0) {
+		CAM_WARN(CAM_CRM, "Buffer at idx=%d is already unmapped,",
+			idx);
+		mutex_unlock(&tbl.m_lock);
+		return 0;
+	}
+
 
 	if (tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS)
 		if (tbl.bufq[idx].i_hdl && tbl.bufq[idx].kmdvaddr)
@@ -856,8 +869,11 @@
 	tbl.bufq[idx].is_imported = false;
 	tbl.bufq[idx].len = 0;
 	tbl.bufq[idx].num_hdl = 0;
+	tbl.bufq[idx].active = false;
 	mutex_unlock(&tbl.bufq[idx].q_lock);
-	cam_mem_put_slot(idx);
+	mutex_destroy(&tbl.bufq[idx].q_lock);
+	clear_bit(idx, tbl.bitmap);
+	mutex_unlock(&tbl.m_lock);
 
 	return rc;
 }
@@ -1043,6 +1059,10 @@
 	}
 
 	if (!tbl.bufq[idx].active) {
+		if (tbl.bufq[idx].vaddr == 0) {
+			CAM_ERR(CAM_CRM, "buffer is released already");
+			return 0;
+		}
 		CAM_ERR(CAM_CRM, "Released buffer state should be active");
 		return -EINVAL;
 	}
@@ -1184,6 +1204,10 @@
 	}
 
 	if (!tbl.bufq[idx].active) {
+		if (tbl.bufq[idx].vaddr == 0) {
+			CAM_ERR(CAM_CRM, "buffer is released already");
+			return 0;
+		}
 		CAM_ERR(CAM_CRM, "Released buffer state should be active");
 		return -EINVAL;
 	}
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index d7a382f..784e90b 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -25,23 +25,6 @@
 
 static struct cam_req_mgr_core_device *g_crm_core_dev;
 
-
-void cam_req_mgr_handle_core_shutdown(void)
-{
-	struct cam_req_mgr_core_session *session;
-	struct cam_req_mgr_core_session *tsession;
-	struct cam_req_mgr_session_info ses_info;
-
-	if (!list_empty(&g_crm_core_dev->session_head)) {
-		list_for_each_entry_safe(session, tsession,
-			&g_crm_core_dev->session_head, entry) {
-			ses_info.session_hdl =
-				session->session_hdl;
-			cam_req_mgr_destroy_session(&ses_info);
-		}
-	}
-}
-
 static int __cam_req_mgr_setup_payload(struct cam_req_mgr_core_workq *workq)
 {
 	int32_t                  i = 0;
@@ -202,11 +185,18 @@
 
 	if (tbl->inject_delay > 0 && (traverse_data->validate_only == false)) {
 		CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
-		apply_data[tbl->pd].req_id = -1;
 		tbl->inject_delay--;
 		/* This pd table is not ready to proceed with asked idx */
 		SET_FAILURE_BIT(traverse_data->result, tbl->pd);
-		return -EAGAIN;
+		apply_data[tbl->pd].req_id = -1;
+		if (tbl->next) {
+			__cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta,
+				tbl->num_slots);
+			traverse_data->idx = next_idx;
+			traverse_data->tbl = tbl->next;
+			rc = __cam_req_mgr_traverse(traverse_data);
+		}
+		return rc;
 	}
 
 	/* Check if req is ready or in skip mode or pd tbl is in skip mode */
@@ -241,8 +231,20 @@
 		}
 	} else {
 		/* This pd table is not ready to proceed with asked idx */
-		SET_FAILURE_BIT(traverse_data->result, tbl->pd);
-		return -EAGAIN;
+		if (tbl->slot[curr_idx].state == CRM_REQ_STATE_APPLIED)
+			SET_SUCCESS_BIT(traverse_data->result, tbl->pd);
+		else
+			SET_FAILURE_BIT(traverse_data->result, tbl->pd);
+
+		apply_data[tbl->pd].req_id = -1;
+		if (tbl->next) {
+			__cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta,
+				tbl->num_slots);
+			traverse_data->idx = next_idx;
+			traverse_data->tbl = tbl->next;
+			rc = __cam_req_mgr_traverse(traverse_data);
+		}
+		return rc;
 	}
 	return 0;
 }
@@ -472,12 +474,14 @@
  *                  traversed through
  * @idx           : index within input request queue
  * @validate_only : Whether to validate only and/or update settings
+ * @result        : Holds the value that indicates which of the pd
+ *                  tables have a req that is ready to be applied
  *
  * @return   : 0 for success, negative for failure
  *
  */
 static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
-	int32_t idx, bool validate_only)
+	int32_t idx, bool validate_only, int *result)
 {
 	int                            rc;
 	struct cam_req_mgr_traverse    traverse_data;
@@ -508,15 +512,18 @@
 	CAM_DBG(CAM_CRM, "SOF: idx %d result %x pd_mask %x rc %d",
 		idx, traverse_data.result, link->pd_mask, rc);
 
-	if (!rc && traverse_data.result == link->pd_mask) {
+	if (!traverse_data.result)
+		return -EAGAIN;
+
+	if (!rc) {
 		CAM_DBG(CAM_CRM,
 			"APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
 			link->link_hdl, idx,
 			apply_data[2].req_id, apply_data[1].req_id,
 			apply_data[0].req_id);
-	} else
-		rc = -EAGAIN;
+	}
 
+	*result = traverse_data.result;
 	return rc;
 }
 
@@ -645,12 +652,16 @@
  * @link     : pointer to link whose input queue and req tbl are
  *             traversed through
  * @slot     : pointer to the current slot being processed
+ * @result   : Holds the value that indicates which of the pd
+ *             tables have a req that is ready to be applied
+ *
  * @return   : 0 for success, negative for failure
  *
  */
 static int __cam_req_mgr_process_sync_req(
 	struct cam_req_mgr_core_link *link,
-	struct cam_req_mgr_slot *slot)
+	struct cam_req_mgr_slot *slot,
+	int *result)
 {
 	struct cam_req_mgr_core_link *sync_link = NULL;
 	int64_t req_id = 0;
@@ -675,7 +686,7 @@
 		link->sof_counter++;
 	}
 
-	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, result);
 	if (rc) {
 		CAM_DBG(CAM_CRM,
 			"Req: %lld [My link]not available link: %x, rc=%d",
@@ -687,7 +698,7 @@
 		sync_link->req.in_q, req_id);
 	if (sync_slot_idx != -1) {
 		rc = __cam_req_mgr_check_link_is_ready(
-			sync_link, sync_slot_idx, true);
+			sync_link, sync_slot_idx, true, result);
 		CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
 			sync_slot_idx,
 			sync_link->req.in_q->slot[sync_slot_idx].status,
@@ -698,8 +709,8 @@
 	}
 
 	if ((sync_slot_idx != -1) &&
-	((sync_link->req.in_q->slot[sync_slot_idx].status ==
-	CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
+		((sync_link->req.in_q->slot[sync_slot_idx].status ==
+		CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
 		rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
 		if (rc) {
 			CAM_DBG(CAM_CRM,
@@ -707,7 +718,8 @@
 				req_id, sync_link->link_hdl);
 			goto failure;
 		}
-		__cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+		__cam_req_mgr_check_link_is_ready(link, slot->idx, false,
+			result);
 	} else {
 		CAM_DBG(CAM_CRM,
 			"Req: %lld [Other link] not ready to apply on link: %x",
@@ -724,6 +736,41 @@
 }
 
 /**
+ * __cam_req_mgr_reset_pd_tables()
+ *
+ * @brief    : resets pd tables based on req getting applied on
+ *             from a particular pd table
+ * @link     : pointer to link whose input queue and req tbl are
+ *             traversed through
+ * @slot     : Pointer to the current slot
+ * @result   : indicates request of which pd table was successfully
+ *             processed
+ *
+ */
+static void __cam_req_mgr_reset_pd_tables(
+	struct cam_req_mgr_core_link *link,
+	struct cam_req_mgr_slot *slot,
+	int result)
+{
+	int pd_set_bit = 0;
+	int curr_idx = slot->idx;
+	int no_tables = link->req.num_tbl;
+	int max_pd_delay = link->max_delay;
+	struct cam_req_mgr_req_tbl  *tbl = link->req.l_tbl;
+	struct cam_req_mgr_req_queue *in_q = link->req.in_q;
+
+	while (no_tables) {
+		pd_set_bit = (result & (1 << max_pd_delay));
+		if (pd_set_bit)
+			tbl->slot[curr_idx].state = CRM_REQ_STATE_APPLIED;
+		max_pd_delay--;
+		no_tables--;
+		tbl = tbl->next;
+		__cam_req_mgr_dec_idx(&curr_idx, 1, in_q->num_slots);
+	}
+}
+
+/**
  * __cam_req_mgr_process_req()
  *
  * @brief    : processes read index in request queue and traverse through table
@@ -736,7 +783,7 @@
 static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 	uint32_t trigger)
 {
-	int                                  rc = 0, idx;
+	int                                  rc = 0, idx, result = 0;
 	struct cam_req_mgr_slot             *slot = NULL;
 	struct cam_req_mgr_req_queue        *in_q;
 	struct cam_req_mgr_core_session     *session;
@@ -782,10 +829,11 @@
 		}
 
 		if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)
-			rc = __cam_req_mgr_process_sync_req(link, slot);
+			rc = __cam_req_mgr_process_sync_req(link, slot,
+				&result);
 		else
 			rc = __cam_req_mgr_check_link_is_ready(link,
-				slot->idx, false);
+				slot->idx, false, &result);
 
 		if (rc < 0) {
 			/*
@@ -830,16 +878,25 @@
 		spin_unlock_bh(&link->link_state_spin_lock);
 
 		if (link->trigger_mask == link->subscribe_event) {
-			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
+			if (result == link->pd_mask) {
+				slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
+				CAM_DBG(CAM_CRM, "req %d is applied on link %d",
+					slot->req_id, link->link_hdl);
+				idx = in_q->rd_idx;
+				__cam_req_mgr_dec_idx(
+					&idx, link->max_delay + 1,
+					in_q->num_slots);
+				__cam_req_mgr_reset_req_slot(link, idx);
+			} else {
+				CAM_DBG(CAM_CRM,
+					"Req:%lld not applied on all devices",
+				slot->req_id);
+				__cam_req_mgr_reset_pd_tables(link, slot,
+					result);
+				slot->status = CRM_SLOT_STATUS_REQ_PENDING;
+			}
+
 			link->trigger_mask = 0;
-			CAM_DBG(CAM_CRM, "req %d is applied on link %d",
-				slot->req_id,
-				link->link_hdl);
-			idx = in_q->rd_idx;
-			__cam_req_mgr_dec_idx(
-				&idx, link->max_delay + 1,
-				in_q->num_slots);
-			__cam_req_mgr_reset_req_slot(link, idx);
 		}
 	}
 	mutex_unlock(&session->lock);
@@ -2028,6 +2085,22 @@
 	return rc;
 }
 
+void cam_req_mgr_handle_core_shutdown(void)
+{
+	struct cam_req_mgr_core_session *session;
+	struct cam_req_mgr_core_session *tsession;
+	struct cam_req_mgr_session_info ses_info;
+
+	if (!list_empty(&g_crm_core_dev->session_head)) {
+		list_for_each_entry_safe(session, tsession,
+			&g_crm_core_dev->session_head, entry) {
+			ses_info.session_hdl =
+				session->session_hdl;
+			cam_req_mgr_destroy_session(&ses_info);
+		}
+	}
+}
+
 /* IOCTLs handling section */
 int cam_req_mgr_create_session(
 	struct cam_req_mgr_session_info *ses_info)
@@ -2314,21 +2387,23 @@
 
 	if (!sched_req) {
 		CAM_ERR(CAM_CRM, "csl_req is NULL");
-		rc = -EINVAL;
-		goto end;
+		return -EINVAL;
 	}
 
+	mutex_lock(&g_crm_core_dev->crm_lock);
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(sched_req->link_hdl);
 	if (!link) {
 		CAM_DBG(CAM_CRM, "link ptr NULL %x", sched_req->link_hdl);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto end;
 	}
 
 	session = (struct cam_req_mgr_core_session *)link->parent;
 	if (!session) {
 		CAM_WARN(CAM_CRM, "session ptr NULL %x", sched_req->link_hdl);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto end;
 	}
 
 	CAM_DBG(CAM_CRM, "link %x req %lld, sync_mode %d",
@@ -2351,6 +2426,7 @@
 	CAM_DBG(CAM_CRM, "DONE dev %x req %lld sync_mode %d",
 		sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
 end:
+	mutex_unlock(&g_crm_core_dev->crm_lock);
 	return rc;
 }
 
@@ -2373,11 +2449,13 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&g_crm_core_dev->crm_lock);
 	/* session hdl's priv data is cam session struct */
 	cam_session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(sync_info->session_hdl);
 	if (!cam_session) {
 		CAM_ERR(CAM_CRM, "NULL pointer");
+		mutex_unlock(&g_crm_core_dev->crm_lock);
 		return -EINVAL;
 	}
 
@@ -2414,6 +2492,7 @@
 
 done:
 	mutex_unlock(&cam_session->lock);
+	mutex_unlock(&g_crm_core_dev->crm_lock);
 	return rc;
 }
 
@@ -2439,6 +2518,7 @@
 		goto end;
 	}
 
+	mutex_lock(&g_crm_core_dev->crm_lock);
 	/* session hdl's priv data is cam session struct */
 	session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(flush_info->session_hdl);
@@ -2482,6 +2562,7 @@
 		&link->workq_comp,
 		msecs_to_jiffies(CAM_REQ_MGR_SCHED_REQ_TIMEOUT));
 end:
+	mutex_unlock(&g_crm_core_dev->crm_lock);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 42f8c77..4511a5d 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -79,12 +79,14 @@
  * EMPTY   : indicates req slot is empty
  * PENDING : indicates req slot is waiting for reqs from all devs
  * READY   : indicates req slot is ready to be sent to devs
+ * APPLIED : indicates req slot is already sent to devs
  * INVALID : indicates req slot is not in valid state
  */
 enum crm_req_state {
 	CRM_REQ_STATE_EMPTY,
 	CRM_REQ_STATE_PENDING,
 	CRM_REQ_STATE_READY,
+	CRM_REQ_STATE_APPLIED,
 	CRM_REQ_STATE_INVALID,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c
index 2aa2ab1..2189202 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_timer.c
@@ -82,7 +82,7 @@
 {
 	CAM_DBG(CAM_CRM, "destroy timer %pK", *crm_timer);
 	if (*crm_timer) {
-		del_timer(&(*crm_timer)->sys_timer);
+		del_timer_sync(&(*crm_timer)->sys_timer);
 		kfree(*crm_timer);
 		*crm_timer = NULL;
 	}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index febf922..079f5bb 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -33,6 +33,7 @@
 	power_info->power_setting[0].seq_type = SENSOR_VAF;
 	power_info->power_setting[0].seq_val = CAM_VAF;
 	power_info->power_setting[0].config_val = 1;
+	power_info->power_setting[0].delay = 2;
 
 	power_info->power_down_setting_size = 1;
 	power_info->power_down_setting =
@@ -67,6 +68,18 @@
 		(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
 	power_info = &soc_private->power_info;
 
+	if ((power_info->power_setting == NULL) &&
+		(power_info->power_down_setting == NULL)) {
+		CAM_INFO(CAM_ACTUATOR,
+			"Using default power settings");
+		rc = cam_actuator_construct_default_power_setting(power_info);
+		if (rc < 0) {
+			CAM_ERR(CAM_ACTUATOR,
+				"Construct default actuator power setting failed.");
+			return rc;
+		}
+	}
+
 	/* Parse and fill vreg params for power up settings */
 	rc = msm_camera_fill_vreg_params(
 		&a_ctrl->soc_info,
@@ -93,16 +106,14 @@
 
 	rc = cam_sensor_core_power_up(power_info, soc_info);
 	if (rc) {
-		CAM_ERR(CAM_ACTUATOR, "failed in ois power up rc %d", rc);
+		CAM_ERR(CAM_ACTUATOR,
+			"failed in actuator power up rc %d", rc);
 		return rc;
 	}
 
-	/* VREG needs some delay to power up */
-	usleep_range(2000, 2050);
-
 	rc = camera_io_init(&a_ctrl->io_master_info);
 	if (rc < 0)
-		CAM_ERR(CAM_ACTUATOR, "cci_init failed: rc: %d", rc);
+		CAM_ERR(CAM_ACTUATOR, "cci init failed: rc: %d", rc);
 
 	return rc;
 }
@@ -115,7 +126,7 @@
 	struct cam_actuator_soc_private  *soc_private;
 
 	if (!a_ctrl) {
-		CAM_ERR(CAM_ACTUATOR, "failed: e_ctrl %pK", a_ctrl);
+		CAM_ERR(CAM_ACTUATOR, "failed: a_ctrl %pK", a_ctrl);
 		return -EINVAL;
 	}
 
@@ -369,23 +380,34 @@
 int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
 	void *arg)
 {
-	int32_t rc = 0;
+	int32_t  rc = 0;
+	int32_t  i = 0;
+	uint32_t total_cmd_buf_in_bytes = 0;
+	size_t   len_of_buff = 0;
+	uint32_t *offset = NULL;
+	uint32_t *cmd_buf = NULL;
 	uint64_t generic_ptr;
-	struct cam_control *ioctl_ctrl = NULL;
-	struct cam_packet *csl_packet = NULL;
+	struct common_header      *cmm_hdr = NULL;
+	struct cam_control        *ioctl_ctrl = NULL;
+	struct cam_packet         *csl_packet = NULL;
 	struct cam_config_dev_cmd config;
-	struct i2c_data_settings *i2c_data = NULL;
+	struct i2c_data_settings  *i2c_data = NULL;
 	struct i2c_settings_array *i2c_reg_settings = NULL;
-	struct cam_cmd_buf_desc *cmd_desc = NULL;
-	size_t len_of_buff = 0;
-	uint32_t *offset = NULL, *cmd_buf;
-	struct cam_req_mgr_add_request add_req;
+	struct cam_cmd_buf_desc   *cmd_desc = NULL;
+	struct cam_req_mgr_add_request  add_req;
+	struct cam_actuator_soc_private *soc_private = NULL;
+	struct cam_sensor_power_ctrl_t  *power_info = NULL;
 
 	if (!a_ctrl || !arg) {
 		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
+	soc_private =
+		(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
+
+	power_info = &soc_private->power_info;
+
 	ioctl_ctrl = (struct cam_control *)arg;
 	if (copy_from_user(&config, (void __user *) ioctl_ctrl->handle,
 		sizeof(config)))
@@ -405,53 +427,99 @@
 		return -EINVAL;
 	}
 
-	csl_packet = (struct cam_packet *)(generic_ptr +
-		config.offset);
+	csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
 	CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
 
-	if ((csl_packet->header.op_code & 0xFFFFFF) ==
-			CAM_ACTUATOR_PACKET_OPCODE_INIT) {
-		i2c_data = &(a_ctrl->i2c_data);
-		i2c_reg_settings = &i2c_data->init_settings;
-
+	switch (csl_packet->header.op_code & 0xFFFFFF) {
+	case CAM_ACTUATOR_PACKET_OPCODE_INIT:
 		offset = (uint32_t *)&csl_packet->payload;
 		offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
 
-		if (csl_packet->num_cmd_buf != 2) {
-			CAM_ERR(CAM_ACTUATOR, "cmd Buffers in Init : %d",
-				csl_packet->num_cmd_buf);
-			return -EINVAL;
+		/* Loop through multiple command buffers */
+		for (i = 0; i < csl_packet->num_cmd_buf; i++) {
+			total_cmd_buf_in_bytes = cmd_desc[i].length;
+			if (!total_cmd_buf_in_bytes)
+				continue;
+			rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
+					(uint64_t *)&generic_ptr, &len_of_buff);
+			if (rc < 0) {
+				CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
+				return rc;
+			}
+			cmd_buf = (uint32_t *)generic_ptr;
+			if (!cmd_buf) {
+				CAM_ERR(CAM_ACTUATOR, "invalid cmd buf");
+				return -EINVAL;
+			}
+			cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+			cmm_hdr = (struct common_header *)cmd_buf;
+
+			switch (cmm_hdr->cmd_type) {
+			case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
+				CAM_DBG(CAM_ACTUATOR,
+					"Received slave info buffer");
+				rc = cam_actuator_slaveInfo_pkt_parser(
+					a_ctrl, cmd_buf);
+				if (rc < 0) {
+					CAM_ERR(CAM_ACTUATOR,
+					"Failed to parse slave info: %d", rc);
+					return rc;
+				}
+				break;
+			case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
+			case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
+				CAM_DBG(CAM_ACTUATOR,
+					"Received power settings buffer");
+				rc = cam_sensor_update_power_settings(
+					cmd_buf,
+					total_cmd_buf_in_bytes,
+					power_info);
+				if (rc) {
+					CAM_ERR(CAM_ACTUATOR,
+					"Failed:parse power settings: %d",
+					rc);
+					return rc;
+				}
+				break;
+			default:
+				CAM_DBG(CAM_ACTUATOR,
+					"Received initSettings buffer");
+				i2c_data = &(a_ctrl->i2c_data);
+				i2c_reg_settings =
+					&i2c_data->init_settings;
+
+				i2c_reg_settings->request_id = 0;
+				i2c_reg_settings->is_settings_valid = 1;
+				rc = cam_sensor_i2c_command_parser(
+					i2c_reg_settings,
+					&cmd_desc[i], 1);
+				if (rc < 0) {
+					CAM_ERR(CAM_ACTUATOR,
+					"Failed:parse init settings: %d",
+					rc);
+					return rc;
+				}
+				break;
+			}
 		}
 
-		rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle,
-			(uint64_t *)&generic_ptr, &len_of_buff);
-		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
-			return rc;
-		}
-		cmd_buf = (uint32_t *)generic_ptr;
-		cmd_buf += cmd_desc->offset / sizeof(uint32_t);
-		rc = cam_actuator_slaveInfo_pkt_parser(a_ctrl, cmd_buf);
-		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, "Failed in parsing the pkt");
-			return rc;
-		}
-		cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t));
-		i2c_data->init_settings.request_id = 0;
-		i2c_reg_settings->is_settings_valid = 1;
-		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
-			&cmd_desc[1], 1);
-		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, "Actuator pkt parsing failed: %d",
-				rc);
-			return rc;
+		if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) {
+			rc = cam_actuator_power_up(a_ctrl);
+			if (rc < 0) {
+				CAM_ERR(CAM_ACTUATOR,
+					" Actuator Power up failed");
+				return rc;
+			}
+			a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG;
 		}
 
 		rc = cam_actuator_apply_settings(a_ctrl,
 			&a_ctrl->i2c_data.init_settings);
-		if (rc < 0)
+		if (rc < 0) {
 			CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings");
+			return rc;
+		}
 
 		/* Delete the request even if the apply is failed */
 		rc = delete_request(&a_ctrl->i2c_data.init_settings);
@@ -460,10 +528,16 @@
 				"Fail in deleting the Init settings");
 			rc = 0;
 		}
-	} else if ((csl_packet->header.op_code & 0xFFFFFF) ==
-		CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS) {
-		a_ctrl->setting_apply_state =
-			ACT_APPLY_SETTINGS_NOW;
+		break;
+	case CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS:
+		if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
+			rc = -EINVAL;
+			CAM_WARN(CAM_ACTUATOR,
+				"Not in right state to move lens: %d",
+				a_ctrl->cam_act_state);
+			return rc;
+		}
+		a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_NOW;
 
 		i2c_data = &(a_ctrl->i2c_data);
 		i2c_reg_settings = &i2c_data->init_settings;
@@ -477,16 +551,22 @@
 		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, "Actuator pkt parsing failed: %d",
-				rc);
+			CAM_ERR(CAM_ACTUATOR,
+				"Auto move lens parsing failed: %d", rc);
 			return rc;
 		}
-	} else if ((csl_packet->header.op_code & 0xFFFFFF) ==
-		CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS) {
+		break;
+	case CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS:
+		if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
+			rc = -EINVAL;
+			CAM_WARN(CAM_ACTUATOR,
+				"Not in right state to move lens: %d",
+				a_ctrl->cam_act_state);
+			return rc;
+		}
 		i2c_data = &(a_ctrl->i2c_data);
-		i2c_reg_settings =
-			&i2c_data->per_frame
-			[csl_packet->header.request_id % MAX_PER_FRAME_ARRAY];
+		i2c_reg_settings = &i2c_data->per_frame[
+			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY];
 
 		i2c_data->init_settings.request_id =
 			csl_packet->header.request_id;
@@ -497,10 +577,11 @@
 		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, "Actuator pkt parsing failed: %d",
-				rc);
+			CAM_ERR(CAM_ACTUATOR,
+				"Manual move lens parsing failed: %d", rc);
 			return rc;
 		}
+		break;
 	}
 
 	if ((csl_packet->header.op_code & 0xFFFFFF) !=
@@ -526,12 +607,13 @@
 	if (a_ctrl->cam_act_state == CAM_ACTUATOR_INIT)
 		return;
 
-	if ((a_ctrl->cam_act_state == CAM_ACTUATOR_START) ||
-		(a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE)) {
+	if (a_ctrl->cam_act_state >= CAM_ACTUATOR_CONFIG) {
 		rc = cam_actuator_power_down(a_ctrl);
 		if (rc < 0)
 			CAM_ERR(CAM_ACTUATOR, "Actuator Power down failed");
+	}
 
+	if (a_ctrl->cam_act_state >= CAM_ACTUATOR_ACQUIRE) {
 		rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl);
 		if (rc < 0)
 			CAM_ERR(CAM_ACTUATOR, "destroying  dhdl failed");
@@ -595,28 +677,24 @@
 			goto release_mutex;
 		}
 
-		rc = cam_actuator_power_up(a_ctrl);
-		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, " Actuator Power up failed");
-			goto release_mutex;
-		}
-
 		a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE;
 	}
 		break;
 	case CAM_RELEASE_DEV: {
-		if (a_ctrl->cam_act_state != CAM_ACTUATOR_ACQUIRE) {
+		if (a_ctrl->cam_act_state == CAM_ACTUATOR_START) {
 			rc = -EINVAL;
 			CAM_WARN(CAM_ACTUATOR,
-			"Not in right state to release : %d",
-			a_ctrl->cam_act_state);
+				"Cant release actuator: in start state");
 			goto release_mutex;
 		}
 
-		rc = cam_actuator_power_down(a_ctrl);
-		if (rc < 0) {
-			CAM_ERR(CAM_ACTUATOR, "Actuator Power down failed");
-			goto release_mutex;
+		if (a_ctrl->cam_act_state == CAM_ACTUATOR_CONFIG) {
+			rc = cam_actuator_power_down(a_ctrl);
+			if (rc < 0) {
+				CAM_ERR(CAM_ACTUATOR,
+					"Actuator Power down failed");
+				goto release_mutex;
+			}
 		}
 
 		if (a_ctrl->bridge_intf.device_hdl == -1) {
@@ -648,7 +726,7 @@
 	}
 		break;
 	case CAM_START_DEV: {
-		if (a_ctrl->cam_act_state != CAM_ACTUATOR_ACQUIRE) {
+		if (a_ctrl->cam_act_state != CAM_ACTUATOR_CONFIG) {
 			rc = -EINVAL;
 			CAM_WARN(CAM_ACTUATOR,
 			"Not in right state to start : %d",
@@ -681,7 +759,7 @@
 						i2c_set->request_id, rc);
 			}
 		}
-		a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE;
+		a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG;
 	}
 		break;
 	case CAM_CONFIG_DEV: {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index c5c9b0a..96fdfeb 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
@@ -183,7 +183,7 @@
 	rc = cam_actuator_parse_dt(a_ctrl, &client->dev);
 	if (rc < 0) {
 		CAM_ERR(CAM_ACTUATOR, "failed: cam_sensor_parse_dt rc %d", rc);
-		goto free_ctrl;
+		goto free_soc;
 	}
 
 	rc = cam_actuator_init_subdev(a_ctrl);
@@ -218,19 +218,10 @@
 
 	v4l2_set_subdevdata(&(a_ctrl->v4l2_dev_str.sd), a_ctrl);
 
-	rc = cam_actuator_construct_default_power_setting(
-		&soc_private->power_info);
-	if (rc < 0) {
-		CAM_ERR(CAM_ACTUATOR,
-			"Construct default actuator power setting failed.");
-		goto free_mem;
-	}
-
 	a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
 
 	return rc;
-free_mem:
-	kfree(a_ctrl->i2c_data.per_frame);
+
 unreg_subdev:
 	cam_unregister_subdev(&(a_ctrl->v4l2_dev_str));
 free_soc:
@@ -311,7 +302,7 @@
 	struct cam_actuator_ctrl_t      *a_ctrl = NULL;
 	struct cam_actuator_soc_private *soc_private = NULL;
 
-	/* Create sensor control structure */
+	/* Create actuator control structure */
 	a_ctrl = devm_kzalloc(&pdev->dev,
 		sizeof(struct cam_actuator_ctrl_t), GFP_KERNEL);
 	if (!a_ctrl)
@@ -379,18 +370,10 @@
 
 	platform_set_drvdata(pdev, a_ctrl);
 	v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, a_ctrl);
-
-	rc = cam_actuator_construct_default_power_setting(
-		&soc_private->power_info);
-	if (rc < 0) {
-		CAM_ERR(CAM_ACTUATOR,
-			"Construct default actuator power setting failed.");
-		goto unreg_subdev;
-	}
+	a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
 
 	return rc;
-unreg_subdev:
-	cam_unregister_subdev(&(a_ctrl->v4l2_dev_str));
+
 free_mem:
 	kfree(a_ctrl->i2c_data.per_frame);
 free_soc:
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h
index 8b8b1ef..c4333a0 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h
@@ -56,6 +56,7 @@
 enum cam_actuator_state {
 	CAM_ACTUATOR_INIT,
 	CAM_ACTUATOR_ACQUIRE,
+	CAM_ACTUATOR_CONFIG,
 	CAM_ACTUATOR_START,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c
index 55b7c72..96dc284 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_soc.c
@@ -46,8 +46,10 @@
 		CAM_DBG(CAM_ACTUATOR, "cci-master %d, rc %d",
 			a_ctrl->cci_i2c_master, rc);
 		if ((rc < 0) || (a_ctrl->cci_i2c_master >= MASTER_MAX)) {
-			CAM_ERR(CAM_ACTUATOR, "Wrong info: dt CCI master:%d",
-				a_ctrl->cci_i2c_master);
+			CAM_ERR(CAM_ACTUATOR,
+				"Wrong info: rc: %d, dt CCI master:%d",
+				rc, a_ctrl->cci_i2c_master);
+			rc = -EFAULT;
 			return rc;
 		}
 	}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
index 6cfb965..ed91250 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
@@ -146,16 +146,16 @@
 			base + CCI_RESET_CMD_ADDR);
 	}
 	if (irq & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) {
-		CAM_ERR(CAM_CCI, "MASTER_0 error 0x%x", irq);
 		cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
 		cam_io_w_mb(CCI_M0_HALT_REQ_RMSK,
 			base + CCI_HALT_REQ_ADDR);
+		CAM_DBG(CAM_CCI, "MASTER_0 error 0x%x", irq);
 	}
 	if (irq & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) {
-		CAM_ERR(CAM_CCI, "MASTER_1 error 0x%x", irq);
 		cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
 		cam_io_w_mb(CCI_M1_HALT_REQ_RMSK,
 			base + CCI_HALT_REQ_ADDR);
+		CAM_DBG(CAM_CCI, "MASTER_1 error 0x%x", irq);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 2adca66..262e49c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -140,12 +140,6 @@
 	csiphy_dev->csiphy_info.data_rate = cam_cmd_csiphy_info->data_rate;
 	csiphy_dev->csiphy_info.secure_mode = cam_cmd_csiphy_info->secure_mode;
 
-	if (csiphy_dev->csiphy_info.secure_mode &&
-		(csiphy_dev->config_count == 1))
-		rc = cam_csiphy_notify_secure_mode(
-			csiphy_dev->soc_info.index,
-			CAM_SECURE_MODE_SECURE);
-
 	return rc;
 }
 
@@ -365,6 +359,14 @@
 	if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
 		soc_info = &csiphy_dev->soc_info;
 
+		if (csiphy_dev->csiphy_info.secure_mode)
+			cam_csiphy_notify_secure_mode(
+				csiphy_dev->soc_info.index,
+				CAM_SECURE_MODE_NON_SECURE);
+
+		csiphy_dev->csiphy_info.secure_mode =
+			CAM_SECURE_MODE_NON_SECURE;
+
 		cam_csiphy_reset(csiphy_dev);
 		cam_soc_util_disable_platform_resource(soc_info, true, true);
 
@@ -393,6 +395,43 @@
 	csiphy_dev->csiphy_state = CAM_CSIPHY_INIT;
 }
 
+static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev,
+	struct cam_config_dev_cmd *p_submit_cmd)
+{
+	struct cam_csiphy_info cam_cmd_csiphy_info;
+	int32_t rc = 0;
+
+	if (copy_from_user(&cam_cmd_csiphy_info,
+		(void __user *)p_submit_cmd->packet_handle,
+		sizeof(struct cam_csiphy_info))) {
+		CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n");
+		rc = -EFAULT;
+	} else {
+		csiphy_dev->csiphy_info.lane_cnt =
+			cam_cmd_csiphy_info.lane_cnt;
+		csiphy_dev->csiphy_info.lane_cnt =
+			cam_cmd_csiphy_info.lane_cnt;
+		csiphy_dev->csiphy_info.lane_mask =
+			cam_cmd_csiphy_info.lane_mask;
+		csiphy_dev->csiphy_info.csiphy_3phase =
+			cam_cmd_csiphy_info.csiphy_3phase;
+		csiphy_dev->csiphy_info.combo_mode =
+			cam_cmd_csiphy_info.combo_mode;
+		csiphy_dev->csiphy_info.settle_time =
+			cam_cmd_csiphy_info.settle_time;
+		csiphy_dev->csiphy_info.data_rate =
+			cam_cmd_csiphy_info.data_rate;
+		CAM_DBG(CAM_CSIPHY,
+			"%s CONFIG_DEV_EXT settle_time= %lld lane_cnt=%d lane_mask=0x%x",
+			__func__,
+			csiphy_dev->csiphy_info.settle_time,
+			csiphy_dev->csiphy_info.lane_cnt,
+			csiphy_dev->csiphy_info.lane_mask);
+	}
+
+	return rc;
+}
+
 int32_t cam_csiphy_core_cfg(void *phy_dev,
 			void *arg)
 {
@@ -516,6 +555,14 @@
 			goto release_mutex;
 		}
 
+		if (csiphy_dev->csiphy_info.secure_mode)
+			cam_csiphy_notify_secure_mode(
+				csiphy_dev->soc_info.index,
+				CAM_SECURE_MODE_NON_SECURE);
+
+		csiphy_dev->csiphy_info.secure_mode =
+			CAM_SECURE_MODE_NON_SECURE;
+
 		rc = cam_csiphy_disable_hw(csiphy_dev);
 		if (rc < 0)
 			CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
@@ -560,15 +607,6 @@
 		csiphy_dev->config_count--;
 		csiphy_dev->acquire_count--;
 
-		if (csiphy_dev->csiphy_info.secure_mode &&
-			(!csiphy_dev->config_count)) {
-			csiphy_dev->csiphy_info.secure_mode =
-				CAM_SECURE_MODE_NON_SECURE;
-			rc = cam_csiphy_notify_secure_mode(
-				csiphy_dev->soc_info.index,
-				CAM_SECURE_MODE_NON_SECURE);
-		}
-
 		if (csiphy_dev->acquire_count == 0)
 			csiphy_dev->csiphy_state = CAM_CSIPHY_INIT;
 	}
@@ -609,6 +647,15 @@
 			goto release_mutex;
 		}
 
+		if (csiphy_dev->csiphy_info.secure_mode) {
+			rc = cam_csiphy_notify_secure_mode(
+				csiphy_dev->soc_info.index,
+				CAM_SECURE_MODE_SECURE);
+			if (rc < 0)
+				csiphy_dev->csiphy_info.secure_mode =
+					CAM_SECURE_MODE_NON_SECURE;
+		}
+
 		rc = cam_csiphy_enable_hw(csiphy_dev);
 		if (rc != 0) {
 			CAM_ERR(CAM_CSIPHY, "cam_csiphy_enable_hw failed");
@@ -629,6 +676,19 @@
 		csiphy_dev->csiphy_state = CAM_CSIPHY_START;
 	}
 		break;
+	case CAM_CONFIG_DEV_EXTERNAL: {
+		struct cam_config_dev_cmd submit_cmd;
+
+		if (copy_from_user(&submit_cmd,
+			(void __user *)cmd->handle,
+			sizeof(struct cam_config_dev_cmd))) {
+			CAM_ERR(CAM_CSIPHY, "failed copy config ext\n");
+			rc = -EFAULT;
+		} else {
+			rc = cam_csiphy_external_cmd(csiphy_dev, &submit_cmd);
+		}
+		break;
+	}
 	default:
 		CAM_ERR(CAM_CSIPHY, "Invalid Opcode: %d", cmd->op_code);
 		rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 3abdd80..b0fbead 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -160,7 +160,7 @@
 		power_info->power_setting_size);
 	if (rc) {
 		CAM_ERR(CAM_EEPROM,
-			"failed to fill vreg params for power up rc:%d", rc);
+			"failed to fill power up vreg params rc:%d", rc);
 		return rc;
 	}
 
@@ -171,7 +171,7 @@
 		power_info->power_down_setting_size);
 	if (rc) {
 		CAM_ERR(CAM_EEPROM,
-			"failed to fill vreg params power down rc:%d", rc);
+			"failed to fill power down vreg params  rc:%d", rc);
 		return rc;
 	}
 
@@ -588,17 +588,18 @@
 					sizeof(struct cam_cmd_i2c_info);
 				processed_cmd_buf_in_bytes +=
 					cmd_length_in_bytes;
-				cmd_buf += cmd_length_in_bytes/4;
+				cmd_buf += cmd_length_in_bytes/
+					sizeof(uint32_t);
 				break;
 			case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
 			case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
-				cmd_length_in_bytes =
-					sizeof(struct cam_cmd_power);
+				cmd_length_in_bytes = total_cmd_buf_in_bytes;
 				rc = cam_sensor_update_power_settings(cmd_buf,
 					cmd_length_in_bytes, power_info);
 				processed_cmd_buf_in_bytes +=
-					total_cmd_buf_in_bytes;
-				cmd_buf += total_cmd_buf_in_bytes/4;
+					cmd_length_in_bytes;
+				cmd_buf += cmd_length_in_bytes/
+					sizeof(uint32_t);
 				if (rc) {
 					CAM_ERR(CAM_EEPROM, "Failed");
 					return rc;
@@ -614,7 +615,7 @@
 					&cmd_length_in_bytes, &num_map);
 				processed_cmd_buf_in_bytes +=
 					cmd_length_in_bytes;
-				cmd_buf += cmd_length_in_bytes/4;
+				cmd_buf += cmd_length_in_bytes/sizeof(uint32_t);
 				break;
 			default:
 				break;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
index f3c4811..68c5eea 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
@@ -419,8 +419,10 @@
 	e_ctrl->io_master_info.master_type = CCI_MASTER;
 	e_ctrl->io_master_info.cci_client = kzalloc(
 		sizeof(struct cam_sensor_cci_client), GFP_KERNEL);
-	if (!e_ctrl->io_master_info.cci_client)
+	if (!e_ctrl->io_master_info.cci_client) {
+		rc = -ENOMEM;
 		goto free_e_ctrl;
+	}
 
 	soc_private = kzalloc(sizeof(struct cam_eeprom_soc_private),
 		GFP_KERNEL);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
index c250045..5a6a401 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
@@ -295,17 +295,17 @@
 		(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
 	uint32_t                        temp;
 
+	if (!soc_info->dev) {
+		CAM_ERR(CAM_EEPROM, "Dev is NULL");
+		return -EINVAL;
+	}
+
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc < 0) {
 		CAM_ERR(CAM_EEPROM, "Failed to read DT properties rc : %d", rc);
 		return rc;
 	}
 
-	if (!soc_info->dev) {
-		CAM_ERR(CAM_EEPROM, "Dev is NULL");
-		return -EINVAL;
-	}
-
 	of_node = soc_info->dev->of_node;
 
 	rc = of_property_read_string(of_node, "eeprom-name",
@@ -318,8 +318,9 @@
 	if (e_ctrl->io_master_info.master_type == CCI_MASTER) {
 		rc = of_property_read_u32(of_node, "cci-master",
 			&e_ctrl->cci_i2c_master);
-		if (rc < 0) {
+		if (rc < 0 || (e_ctrl->cci_i2c_master >= MASTER_MAX)) {
 			CAM_DBG(CAM_EEPROM, "failed rc %d", rc);
+			rc = -EFAULT;
 			return rc;
 		}
 	}
@@ -349,7 +350,7 @@
 				"i2c-freq-mode read fail %d", rc);
 			soc_private->i2c_info.i2c_freq_mode = 0;
 		}
-		if (soc_private->i2c_info.i2c_freq_mode	>= I2C_MAX_MODES) {
+		if (soc_private->i2c_info.i2c_freq_mode >= I2C_MAX_MODES) {
 			CAM_ERR(CAM_EEPROM, "invalid i2c_freq_mode = %d",
 				soc_private->i2c_info.i2c_freq_mode);
 			soc_private->i2c_info.i2c_freq_mode = 0;
@@ -362,7 +363,7 @@
 		soc_info->clk[i] = devm_clk_get(soc_info->dev,
 			soc_info->clk_name[i]);
 		if (!soc_info->clk[i]) {
-			CAM_ERR(CAM_SENSOR, "get failed for %s",
+			CAM_ERR(CAM_EEPROM, "get failed for %s",
 				soc_info->clk_name[i]);
 			rc = -ENOENT;
 			return rc;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
index c977fc4..e0d4502 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -36,7 +36,6 @@
 			return rc;
 		}
 		flash_ctrl->is_regulator_enabled = true;
-		flash_ctrl->flash_state = CAM_FLASH_STATE_START;
 	} else if ((!regulator_enable) &&
 		(flash_ctrl->is_regulator_enabled == true)) {
 		rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
@@ -47,7 +46,6 @@
 			return rc;
 		}
 		flash_ctrl->is_regulator_enabled = false;
-		flash_ctrl->flash_state = CAM_FLASH_STATE_ACQUIRE;
 	} else {
 		CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
 			flash_ctrl->flash_state);
@@ -68,12 +66,14 @@
 	nrt_settings = &fctrl->nrt_info;
 
 	if (nrt_settings->cmn_attr.cmd_type ==
-		CAMERA_SENSOR_FLASH_CMD_TYPE_INIT) {
+		CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO) {
 		fctrl->flash_init_setting.cmn_attr.is_settings_valid = false;
 	} else if ((nrt_settings->cmn_attr.cmd_type ==
 		CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) ||
 		(nrt_settings->cmn_attr.cmd_type ==
-		CAMERA_SENSOR_FLASH_CMD_TYPE_RER)) {
+		CAMERA_SENSOR_FLASH_CMD_TYPE_RER) ||
+		(nrt_settings->cmn_attr.cmd_type ==
+		CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE)) {
 		fctrl->nrt_info.cmn_attr.is_settings_valid = false;
 		fctrl->nrt_info.cmn_attr.count = 0;
 		fctrl->nrt_info.num_iterations = 0;
@@ -312,6 +312,49 @@
 
 	if (req_id == 0) {
 		if (fctrl->nrt_info.cmn_attr.cmd_type ==
+			CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE) {
+			flash_data = &fctrl->nrt_info;
+			if (flash_data->opcode ==
+				CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
+				if (fctrl->flash_state !=
+					CAM_FLASH_STATE_CONFIG) {
+					CAM_WARN(CAM_FLASH,
+					"Cannot apply Start Dev:Prev state: %d",
+					fctrl->flash_state);
+					return rc;
+				}
+				rc = cam_flash_prepare(fctrl, true);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+					"Enable Regulator Failed rc = %d", rc);
+					return rc;
+				}
+				rc = cam_flash_high(fctrl, flash_data);
+				if (rc)
+					CAM_ERR(CAM_FLASH,
+						"FLASH ON failed : %d",
+						rc);
+			}
+			if (flash_data->opcode ==
+				CAMERA_SENSOR_FLASH_OP_OFF) {
+				rc = cam_flash_off(fctrl);
+				if (rc) {
+					CAM_ERR(CAM_FLASH,
+					"LED OFF FAILED: %d",
+					rc);
+					return rc;
+				}
+				if ((fctrl->flash_state ==
+					CAM_FLASH_STATE_START) &&
+					(fctrl->is_regulator_enabled == true)) {
+					rc = cam_flash_prepare(fctrl, false);
+					if (rc)
+						CAM_ERR(CAM_FLASH,
+						"Disable Regulator failed: %d",
+						rc);
+				}
+			}
+		} else if (fctrl->nrt_info.cmn_attr.cmd_type ==
 			CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) {
 			flash_data = &fctrl->nrt_info;
 			if (flash_data->opcode ==
@@ -491,11 +534,39 @@
 		cam_flash_info = (struct cam_flash_init *)cmd_buf;
 
 		switch (cam_flash_info->cmd_type) {
-		case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT:
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO:
 			fctrl->flash_type = cam_flash_info->flash_type;
 			fctrl->is_regulator_enabled = false;
 			fctrl->nrt_info.cmn_attr.cmd_type =
-				CAMERA_SENSOR_FLASH_CMD_TYPE_INIT;
+				CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO;
+			fctrl->flash_state =
+				CAM_FLASH_STATE_CONFIG;
+			break;
+		case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE:
+			CAM_DBG(CAM_FLASH, "Widget Flash Operation");
+				flash_operation_info =
+					(struct cam_flash_set_on_off *) cmd_buf;
+				fctrl->nrt_info.cmn_attr.count =
+					flash_operation_info->count;
+				fctrl->nrt_info.cmn_attr.request_id = 0;
+				fctrl->nrt_info.opcode =
+					flash_operation_info->opcode;
+				fctrl->nrt_info.cmn_attr.cmd_type =
+					CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE;
+				for (i = 0;
+					i < flash_operation_info->count; i++)
+					fctrl->nrt_info.led_current_ma[i] =
+					flash_operation_info->led_current_ma[i];
+
+				mutex_lock(&fctrl->flash_wq_mutex);
+				rc = cam_flash_apply_setting(fctrl, 0);
+				if (rc)
+					CAM_ERR(CAM_FLASH,
+						"Apply setting failed: %d",
+						rc);
+				mutex_unlock(&fctrl->flash_wq_mutex);
+				fctrl->flash_state =
+					CAM_FLASH_STATE_CONFIG;
 			break;
 		default:
 			CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
@@ -541,28 +612,35 @@
 		case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: {
 			CAM_DBG(CAM_FLASH,
 				"CAMERA_FLASH_CMD_TYPE_OPS case called");
-			if (fctrl->flash_state != CAM_FLASH_STATE_START) {
+			if ((fctrl->flash_state == CAM_FLASH_STATE_START) ||
+				(fctrl->flash_state ==
+					CAM_FLASH_STATE_CONFIG)) {
+				flash_operation_info =
+					(struct cam_flash_set_on_off *) cmd_buf;
+				if (!flash_operation_info) {
+					CAM_ERR(CAM_FLASH,
+						"flash_operation_info Null");
+					return -EINVAL;
+				}
+
+				fctrl->per_frame[frame_offset].opcode =
+					flash_operation_info->opcode;
+				fctrl->per_frame[frame_offset].cmn_attr.count =
+					flash_operation_info->count;
+				for (i = 0;
+					i < flash_operation_info->count; i++)
+					fctrl->per_frame[frame_offset].
+						led_current_ma[i]
+						= flash_operation_info->
+						led_current_ma[i];
+
+			} else {
 				CAM_ERR(CAM_FLASH,
 					"Rxed Update packets without linking");
 				fctrl->per_frame[frame_offset].
 					cmn_attr.is_settings_valid = false;
 				return -EINVAL;
 			}
-			flash_operation_info =
-				(struct cam_flash_set_on_off *) cmd_buf;
-			if (!flash_operation_info) {
-				CAM_ERR(CAM_FLASH, "flash_operation_info Null");
-				return -EINVAL;
-			}
-
-			fctrl->per_frame[frame_offset].opcode =
-				flash_operation_info->opcode;
-			fctrl->per_frame[frame_offset].cmn_attr.count =
-				flash_operation_info->count;
-			for (i = 0; i < flash_operation_info->count; i++)
-				fctrl->per_frame[frame_offset].led_current_ma[i]
-					= flash_operation_info->
-					led_current_ma[i];
 			break;
 		}
 		default:
@@ -663,17 +741,18 @@
 		break;
 	}
 	case CAM_PKT_NOP_OPCODE: {
-		if (fctrl->flash_state != CAM_FLASH_STATE_START) {
+		if ((fctrl->flash_state == CAM_FLASH_STATE_START) ||
+			(fctrl->flash_state == CAM_FLASH_STATE_CONFIG)) {
+			CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
+				csl_packet->header.request_id);
+			goto update_req_mgr;
+		} else {
 			CAM_ERR(CAM_FLASH,
 				"Rxed Update packets without linking");
 			fctrl->per_frame[frame_offset].
 				cmn_attr.is_settings_valid = false;
 			return -EINVAL;
 		}
-
-		CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
-			csl_packet->header.request_id);
-		goto update_req_mgr;
 	}
 	default:
 		CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
@@ -795,15 +874,13 @@
 	if (fctrl->flash_state == CAM_FLASH_STATE_INIT)
 		return;
 
-	if (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE) {
-		cam_flash_release_dev(fctrl);
-		return;
+	if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) ||
+		(fctrl->flash_state == CAM_FLASH_STATE_START)) {
+		rc = cam_flash_stop_dev(fctrl);
+		if (rc)
+			CAM_ERR(CAM_FLASH, "Stop Failed rc: %d", rc);
 	}
 
-	rc = cam_flash_stop_dev(fctrl);
-	if (rc)
-		CAM_ERR(CAM_FLASH, "Stop Failed rc: %d", rc);
-
 	rc = cam_flash_release_dev(fctrl);
 	if (rc)
 		CAM_ERR(CAM_FLASH, "Release failed rc: %d", rc);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
index e00d4fd..eddbf97 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -131,7 +131,7 @@
 	}
 	case CAM_START_DEV: {
 		CAM_DBG(CAM_FLASH, "CAM_START_DEV");
-		if (fctrl->flash_state != CAM_FLASH_STATE_ACQUIRE) {
+		if (fctrl->flash_state != CAM_FLASH_STATE_CONFIG) {
 			CAM_WARN(CAM_FLASH,
 				"Cannot apply Start Dev: Prev state: %d",
 				fctrl->flash_state);
@@ -154,6 +154,7 @@
 		break;
 	}
 	case CAM_STOP_DEV: {
+		CAM_DBG(CAM_FLASH, "CAM_STOP_DEV ENTER");
 		if (fctrl->flash_state != CAM_FLASH_STATE_START) {
 			CAM_WARN(CAM_FLASH,
 				"Cannot apply Stop dev: Prev state is: %d",
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
index a1f8f67..92726a9 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
@@ -50,6 +50,7 @@
 enum cam_flash_state {
 	CAM_FLASH_STATE_INIT,
 	CAM_FLASH_STATE_ACQUIRE,
+	CAM_FLASH_STATE_CONFIG,
 	CAM_FLASH_STATE_START,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index 4e4b112..76f5b46 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -35,6 +35,7 @@
 	power_info->power_setting[0].seq_type = SENSOR_VAF;
 	power_info->power_setting[0].seq_val = CAM_VAF;
 	power_info->power_setting[0].config_val = 1;
+	power_info->power_setting[0].delay = 2;
 
 	power_info->power_down_setting_size = 1;
 	power_info->power_down_setting =
@@ -112,9 +113,21 @@
 		(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
 	power_info = &soc_private->power_info;
 
+	if ((power_info->power_setting == NULL) &&
+		(power_info->power_down_setting == NULL)) {
+		CAM_INFO(CAM_OIS,
+			"Using default power settings");
+		rc = cam_ois_construct_default_power_setting(power_info);
+		if (rc < 0) {
+			CAM_ERR(CAM_OIS,
+				"Construct default ois power setting failed.");
+			return rc;
+		}
+	}
+
 	/* Parse and fill vreg params for power up settings */
 	rc = msm_camera_fill_vreg_params(
-		&o_ctrl->soc_info,
+		soc_info,
 		power_info->power_setting,
 		power_info->power_setting_size);
 	if (rc) {
@@ -125,12 +138,12 @@
 
 	/* Parse and fill vreg params for power down settings*/
 	rc = msm_camera_fill_vreg_params(
-		&o_ctrl->soc_info,
+		soc_info,
 		power_info->power_down_setting,
 		power_info->power_down_setting_size);
 	if (rc) {
 		CAM_ERR(CAM_OIS,
-			"failed to fill vreg params power down rc:%d", rc);
+			"failed to fill vreg params for power down rc:%d", rc);
 		return rc;
 	}
 
@@ -142,9 +155,6 @@
 		return rc;
 	}
 
-	/* VREG needs some delay to power up */
-	usleep_range(2000, 2050);
-
 	rc = camera_io_init(&o_ctrl->io_master_info);
 	if (rc)
 		CAM_ERR(CAM_OIS, "cci_init failed: rc: %d", rc);
@@ -152,6 +162,12 @@
 	return rc;
 }
 
+/**
+ * cam_ois_power_down - power down OIS device
+ * @o_ctrl:     ctrl structure
+ *
+ * Returns success or failure
+ */
 static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl)
 {
 	int32_t                         rc = 0;
@@ -392,6 +408,9 @@
 static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
 {
 	int32_t                         rc = 0;
+	int32_t                         i = 0;
+	uint32_t                        total_cmd_buf_in_bytes = 0;
+	struct common_header           *cmm_hdr = NULL;
 	uint64_t                        generic_ptr;
 	struct cam_control             *ioctl_ctrl = NULL;
 	struct cam_config_dev_cmd       dev_config;
@@ -402,6 +421,9 @@
 	struct cam_packet              *csl_packet = NULL;
 	size_t                          len_of_buff = 0;
 	uint32_t                       *offset = NULL, *cmd_buf;
+	struct cam_ois_soc_private     *soc_private =
+		(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
+	struct cam_sensor_power_ctrl_t  *power_info = &soc_private->power_info;
 
 	ioctl_ctrl = (struct cam_control *)arg;
 	if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
@@ -430,52 +452,94 @@
 		offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
 
-		if ((csl_packet->num_cmd_buf < 2) &&
-			(csl_packet->num_cmd_buf > 3)) {
-			CAM_ERR(CAM_OIS, "wrong cmd Buffer count: %d",
-				csl_packet->num_cmd_buf);
-			return -EINVAL;
-		}
+		/* Loop through multiple command buffers */
+		for (i = 0; i < csl_packet->num_cmd_buf; i++) {
+			total_cmd_buf_in_bytes = cmd_desc[i].length;
+			if (!total_cmd_buf_in_bytes)
+				continue;
 
-		rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle,
-			(uint64_t *)&generic_ptr, &len_of_buff);
-		if (rc < 0) {
-			CAM_ERR(CAM_OIS, "Failed to get cpu buf");
-			return rc;
-		}
-
-		cmd_buf = (uint32_t *)generic_ptr;
-		cmd_buf += cmd_desc->offset / sizeof(uint32_t);
-		rc = cam_ois_slaveInfo_pkt_parser(o_ctrl, cmd_buf);
-		if (rc < 0) {
-			CAM_ERR(CAM_OIS, "Failed in parsing the pkt");
-			return rc;
-		}
-
-		cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t));
-
-		i2c_reg_settings = &(o_ctrl->i2c_init_data);
-		i2c_reg_settings->is_settings_valid = 1;
-		i2c_reg_settings->request_id = 0;
-		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
-			&cmd_desc[1], 1);
-		if (rc < 0) {
-			CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d",
-				rc);
-			return rc;
-		}
-
-		if (o_ctrl->is_ois_calib) {
-			i2c_reg_settings = &(o_ctrl->i2c_calib_data);
-			i2c_reg_settings->is_settings_valid = 1;
-			i2c_reg_settings->request_id = 0;
-			rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
-				&cmd_desc[2], 1);
+			rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
+				(uint64_t *)&generic_ptr, &len_of_buff);
 			if (rc < 0) {
-				CAM_ERR(CAM_OIS,
-					"OIS pkt parsing failed: %d", rc);
+				CAM_ERR(CAM_OIS, "Failed to get cpu buf");
 				return rc;
 			}
+			cmd_buf = (uint32_t *)generic_ptr;
+			if (!cmd_buf) {
+				CAM_ERR(CAM_OIS, "invalid cmd buf");
+				return -EINVAL;
+			}
+			cmd_buf += cmd_desc->offset / sizeof(uint32_t);
+			cmm_hdr = (struct common_header *)cmd_buf;
+
+			switch (cmm_hdr->cmd_type) {
+			case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
+				rc = cam_ois_slaveInfo_pkt_parser(
+					o_ctrl, cmd_buf);
+				if (rc < 0) {
+					CAM_ERR(CAM_OIS,
+					"Failed in parsing slave info");
+					return rc;
+				}
+				break;
+			case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
+			case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
+				CAM_DBG(CAM_OIS,
+					"Received power settings buffer");
+				rc = cam_sensor_update_power_settings(
+					cmd_buf,
+					total_cmd_buf_in_bytes,
+					power_info);
+				if (rc) {
+					CAM_ERR(CAM_OIS,
+					"Failed: parse power settings");
+					return rc;
+				}
+				break;
+			default:
+			if (o_ctrl->i2c_init_data.is_settings_valid == 0) {
+				CAM_DBG(CAM_OIS,
+				"Received init settings");
+				i2c_reg_settings =
+					&(o_ctrl->i2c_init_data);
+				i2c_reg_settings->is_settings_valid = 1;
+				i2c_reg_settings->request_id = 0;
+				rc = cam_sensor_i2c_command_parser(
+					i2c_reg_settings,
+					&cmd_desc[i], 1);
+				if (rc < 0) {
+					CAM_ERR(CAM_OIS,
+					"init parsing failed: %d", rc);
+					return rc;
+				}
+			} else if ((o_ctrl->is_ois_calib != 0) &&
+				(o_ctrl->i2c_calib_data.
+					is_settings_valid == 0)) {
+				CAM_DBG(CAM_OIS,
+					"Received calib settings");
+				i2c_reg_settings = &(o_ctrl->i2c_calib_data);
+				i2c_reg_settings->is_settings_valid = 1;
+				i2c_reg_settings->request_id = 0;
+				rc = cam_sensor_i2c_command_parser(
+					i2c_reg_settings,
+					&cmd_desc[i], 1);
+				if (rc < 0) {
+					CAM_ERR(CAM_OIS,
+						"Calib parsing failed: %d", rc);
+					return rc;
+				}
+			}
+			break;
+			}
+		}
+
+		if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) {
+			rc = cam_ois_power_up(o_ctrl);
+			if (rc) {
+				CAM_ERR(CAM_OIS, " OIS Power up failed");
+				return rc;
+			}
+			o_ctrl->cam_ois_state = CAM_OIS_CONFIG;
 		}
 
 		if (o_ctrl->ois_fw_flag) {
@@ -515,6 +579,13 @@
 		}
 		break;
 	case CAM_OIS_PACKET_OPCODE_OIS_CONTROL:
+		if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {
+			rc = -EINVAL;
+			CAM_WARN(CAM_OIS,
+				"Not in right state to control OIS: %d",
+				o_ctrl->cam_ois_state);
+			return rc;
+		}
 		offset = (uint32_t *)&csl_packet->payload;
 		offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
@@ -555,12 +626,13 @@
 	if (o_ctrl->cam_ois_state == CAM_OIS_INIT)
 		return;
 
-	if ((o_ctrl->cam_ois_state == CAM_OIS_START) ||
-		(o_ctrl->cam_ois_state == CAM_OIS_ACQUIRE)) {
+	if (o_ctrl->cam_ois_state >= CAM_OIS_CONFIG) {
 		rc = cam_ois_power_down(o_ctrl);
 		if (rc < 0)
 			CAM_ERR(CAM_OIS, "OIS Power down failed");
+	}
 
+	if (o_ctrl->cam_ois_state >= CAM_OIS_ACQUIRE) {
 		rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl);
 		if (rc < 0)
 			CAM_ERR(CAM_OIS, "destroying the device hdl");
@@ -611,16 +683,10 @@
 			goto release_mutex;
 		}
 
-		rc = cam_ois_power_up(o_ctrl);
-		if (rc) {
-			CAM_ERR(CAM_OIS, " OIS Power up failed");
-			goto release_mutex;
-		}
-
 		o_ctrl->cam_ois_state = CAM_OIS_ACQUIRE;
 		break;
 	case CAM_START_DEV:
-		if (o_ctrl->cam_ois_state != CAM_OIS_ACQUIRE) {
+		if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) {
 			rc = -EINVAL;
 			CAM_WARN(CAM_OIS,
 			"Not in right state for start : %d",
@@ -637,18 +703,19 @@
 		}
 		break;
 	case CAM_RELEASE_DEV:
-		if (o_ctrl->cam_ois_state != CAM_OIS_ACQUIRE) {
+		if (o_ctrl->cam_ois_state == CAM_OIS_START) {
 			rc = -EINVAL;
 			CAM_WARN(CAM_OIS,
-			"Not in right state for release : %d",
-			o_ctrl->cam_ois_state);
+				"Cant release ois: in start state");
 			goto release_mutex;
 		}
 
-		rc = cam_ois_power_down(o_ctrl);
-		if (rc < 0) {
-			CAM_ERR(CAM_OIS, "OIS Power down failed");
-			goto release_mutex;
+		if (o_ctrl->cam_ois_state == CAM_OIS_CONFIG) {
+			rc = cam_ois_power_down(o_ctrl);
+			if (rc < 0) {
+				CAM_ERR(CAM_OIS, "OIS Power down failed");
+				goto release_mutex;
+			}
 		}
 
 		if (o_ctrl->bridge_intf.device_hdl == -1) {
@@ -673,7 +740,7 @@
 			"Not in right state for stop : %d",
 			o_ctrl->cam_ois_state);
 		}
-		o_ctrl->cam_ois_state = CAM_OIS_ACQUIRE;
+		o_ctrl->cam_ois_state = CAM_OIS_CONFIG;
 		break;
 	default:
 		CAM_ERR(CAM_OIS, "invalid opcode");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
index 5e1d719..d742acf 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
@@ -197,27 +197,19 @@
 	rc = cam_ois_driver_soc_init(o_ctrl);
 	if (rc) {
 		CAM_ERR(CAM_OIS, "failed: cam_sensor_parse_dt rc %d", rc);
-		goto octrl_free;
+		goto soc_free;
 	}
 
 	rc = cam_ois_init_subdev_param(o_ctrl);
 	if (rc)
-		goto octrl_free;
-
-	rc = cam_ois_construct_default_power_setting(
-		&soc_private->power_info);
-	if (rc < 0) {
-		CAM_ERR(CAM_OIS,
-			"Construct default ois power setting failed.");
-		goto unreg_subdev;
-	}
+		goto soc_free;
 
 	o_ctrl->cam_ois_state = CAM_OIS_INIT;
 
 	return rc;
 
-unreg_subdev:
-	cam_unregister_subdev(&(o_ctrl->v4l2_dev_str));
+soc_free:
+	kfree(soc_private);
 octrl_free:
 	kfree(o_ctrl);
 probe_failure:
@@ -285,6 +277,7 @@
 		goto free_cci_client;
 	}
 	o_ctrl->soc_info.soc_private = soc_private;
+	soc_private->power_info.dev  = &pdev->dev;
 
 	INIT_LIST_HEAD(&(o_ctrl->i2c_init_data.list_head));
 	INIT_LIST_HEAD(&(o_ctrl->i2c_calib_data.list_head));
@@ -307,14 +300,6 @@
 	}
 	o_ctrl->bridge_intf.device_hdl = -1;
 
-	rc = cam_ois_construct_default_power_setting(
-		&soc_private->power_info);
-	if (rc < 0) {
-		CAM_ERR(CAM_OIS,
-			"Construct default ois power setting failed.");
-		goto unreg_subdev;
-	}
-
 	platform_set_drvdata(pdev, o_ctrl);
 	v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, o_ctrl);
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h
index 80f1e84..3b7195e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h
@@ -34,6 +34,7 @@
 enum cam_ois_state {
 	CAM_OIS_INIT,
 	CAM_OIS_ACQUIRE,
+	CAM_OIS_CONFIG,
 	CAM_OIS_START,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index ec37c84..9ce7a21 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -165,38 +165,41 @@
 	}
 
 	case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: {
-		if (s_ctrl->sensor_state != CAM_SENSOR_START) {
+		if ((s_ctrl->sensor_state == CAM_SENSOR_CONFIG) ||
+			(s_ctrl->sensor_state == CAM_SENSOR_START)) {
+			i2c_reg_settings =
+				&i2c_data->
+				per_frame[csl_packet->header.request_id %
+				MAX_PER_FRAME_ARRAY];
+			CAM_DBG(CAM_SENSOR, "Received Packet: %lld",
+			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY);
+			if (i2c_reg_settings->is_settings_valid == 1) {
+				CAM_ERR(CAM_SENSOR,
+					"Already some pkt in offset req : %lld",
+					csl_packet->header.request_id);
+				rc = delete_request(i2c_reg_settings);
+				if (rc < 0) {
+					CAM_ERR(CAM_SENSOR,
+					"Failed in Deleting the err: %d", rc);
+					return rc;
+				}
+			}
+		} else {
 			CAM_ERR(CAM_SENSOR,
 				"Rxed Update packets without linking");
 			return -EINVAL;
 		}
-		i2c_reg_settings =
-			&i2c_data->
-			per_frame[csl_packet->header.request_id %
-			MAX_PER_FRAME_ARRAY];
-		CAM_DBG(CAM_SENSOR, "Received Packet: %lld",
-			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY);
-		if (i2c_reg_settings->is_settings_valid == 1) {
-			CAM_ERR(CAM_SENSOR,
-				"Already some pkt in offset req : %lld",
-				csl_packet->header.request_id);
-			rc = delete_request(i2c_reg_settings);
-			if (rc < 0) {
-				CAM_ERR(CAM_SENSOR,
-					"Failed in Deleting the err: %d", rc);
-				return rc;
-			}
-		}
 	break;
 	}
 	case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: {
-		if (s_ctrl->sensor_state != CAM_SENSOR_START) {
+		if ((s_ctrl->sensor_state == CAM_SENSOR_CONFIG) ||
+			(s_ctrl->sensor_state == CAM_SENSOR_START)) {
+			cam_sensor_update_req_mgr(s_ctrl, csl_packet);
+		} else {
 			CAM_ERR(CAM_SENSOR,
 				"Rxed Update packets without linking");
-			return -EINVAL;
+			rc = -EINVAL;
 		}
-
-		cam_sensor_update_req_mgr(s_ctrl, csl_packet);
 		return rc;
 	}
 	default:
@@ -487,22 +490,18 @@
 
 	cam_sensor_release_resource(s_ctrl);
 
-	if ((s_ctrl->sensor_state == CAM_SENSOR_START) ||
-		(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
+	if (s_ctrl->sensor_state >= CAM_SENSOR_ACQUIRE)
 		cam_sensor_power_down(s_ctrl);
-		rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
-		if (rc < 0)
-			CAM_ERR(CAM_SENSOR, " failed destroying dhdl");
-		s_ctrl->bridge_intf.device_hdl = -1;
-		s_ctrl->bridge_intf.link_hdl = -1;
-		s_ctrl->bridge_intf.session_hdl = -1;
-		s_ctrl->sensor_state = CAM_SENSOR_PROBE;
-	}
 
-	if (s_ctrl->sensor_state == CAM_SENSOR_PROBE) {
-		kfree(power_info->power_setting);
-		kfree(power_info->power_down_setting);
-	}
+	rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
+	if (rc < 0)
+		CAM_ERR(CAM_SENSOR, " failed destroying dhdl");
+	s_ctrl->bridge_intf.device_hdl = -1;
+	s_ctrl->bridge_intf.link_hdl = -1;
+	s_ctrl->bridge_intf.session_hdl = -1;
+
+	kfree(power_info->power_setting);
+	kfree(power_info->power_down_setting);
 
 	s_ctrl->sensor_state = CAM_SENSOR_INIT;
 }
@@ -625,7 +624,6 @@
 		rc = cam_sensor_power_up(s_ctrl);
 		if (rc < 0) {
 			CAM_ERR(CAM_SENSOR, "power up failed");
-			cam_sensor_power_down(s_ctrl);
 			kfree(pu);
 			kfree(pd);
 			goto release_mutex;
@@ -708,7 +706,8 @@
 	}
 		break;
 	case CAM_RELEASE_DEV: {
-		if (s_ctrl->sensor_state != CAM_SENSOR_ACQUIRE) {
+		if ((s_ctrl->sensor_state < CAM_SENSOR_ACQUIRE) ||
+			(s_ctrl->sensor_state > CAM_SENSOR_CONFIG)) {
 			rc = -EINVAL;
 			CAM_WARN(CAM_SENSOR,
 			"Not in right state to release : %d",
@@ -755,7 +754,7 @@
 		break;
 	}
 	case CAM_START_DEV: {
-		if (s_ctrl->sensor_state != CAM_SENSOR_ACQUIRE) {
+		if (s_ctrl->sensor_state != CAM_SENSOR_CONFIG) {
 			rc = -EINVAL;
 			CAM_WARN(CAM_SENSOR,
 			"Not in right state to start : %d",
@@ -837,6 +836,7 @@
 					"Fail in deleting the config settings");
 				goto release_mutex;
 			}
+			s_ctrl->sensor_state = CAM_SENSOR_CONFIG;
 			s_ctrl->i2c_data.config_settings.request_id = -1;
 		}
 	}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
index 8c49837..624ea29 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
@@ -51,8 +51,8 @@
 
 enum cam_sensor_state_t {
 	CAM_SENSOR_INIT,
-	CAM_SENSOR_PROBE,
 	CAM_SENSOR_ACQUIRE,
+	CAM_SENSOR_CONFIG,
 	CAM_SENSOR_START,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 2e91efc..72ca737 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -50,11 +50,13 @@
 	CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR,
 	CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD,
 	CAMERA_SENSOR_CMD_TYPE_WAIT,
-	CAMERA_SENSOR_FLASH_CMD_TYPE_INIT,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO,
 	CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE,
 	CAMERA_SENSOR_FLASH_CMD_TYPE_RER,
 	CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR,
 	CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET,
+	CAMERA_SENSOR_CMD_TYPE_RD_DATA,
+	CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE,
 	CAMERA_SENSOR_CMD_TYPE_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 535264d..82ba24f 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -676,14 +676,12 @@
 			struct cam_cmd_power *pwr_cmd =
 				(struct cam_cmd_power *)ptr;
 
-			power_info->
-				power_setting_size +=
-				pwr_cmd->count;
+			power_info->power_setting_size += pwr_cmd->count;
 			scr = ptr + sizeof(struct cam_cmd_power);
 			tot_size = tot_size + sizeof(struct cam_cmd_power);
 
 			if (pwr_cmd->count == 0)
-				CAM_DBG(CAM_SENSOR, "Un expected Command");
+				CAM_WARN(CAM_SENSOR, "Un expected Command");
 
 			for (i = 0; i < pwr_cmd->count; i++, pwr_up++) {
 				power_info->
@@ -979,7 +977,7 @@
 		GFP_KERNEL);
 	if (!*pgpio_num_info)
 		return -ENOMEM;
-	gpio_num_info =  *pgpio_num_info;
+	gpio_num_info = *pgpio_num_info;
 
 	rc = of_property_read_u32(of_node, "gpio-vana", &val);
 	if (rc != -EINVAL) {
@@ -1266,6 +1264,8 @@
 		CAM_ERR(CAM_SENSOR,
 			"Cannot set shared pin to active state");
 
+	CAM_DBG(CAM_SENSOR, "power setting size: %d", ctrl->power_setting_size);
+
 	for (index = 0; index < ctrl->power_setting_size; index++) {
 		CAM_DBG(CAM_SENSOR, "index: %d", index);
 		power_setting = &ctrl->power_setting[index];
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index ae9f74c..46e9d5d 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -254,6 +254,12 @@
 		signalable_row = sync_dev->sync_table + list_info->sync_obj;
 
 		spin_lock_bh(&sync_dev->row_spinlocks[list_info->sync_obj]);
+		if (signalable_row->state == CAM_SYNC_STATE_INVALID) {
+			spin_unlock_bh(
+				&sync_dev->row_spinlocks[list_info->sync_obj]);
+			continue;
+		}
+
 		/* Dispatch kernel callbacks if any were registered earlier */
 		list_for_each_entry_safe(sync_cb,
 			temp_sync_cb, &signalable_row->callback_list, list) {
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index 826253c..afac68d 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
@@ -306,6 +306,10 @@
 	row->state = CAM_SYNC_STATE_INVALID;
 	memset(row, 0, sizeof(*row));
 	clear_bit(idx, sync_dev->bitmap);
+	INIT_LIST_HEAD(&row->callback_list);
+	INIT_LIST_HEAD(&row->parents_list);
+	INIT_LIST_HEAD(&row->children_list);
+	INIT_LIST_HEAD(&row->user_payload_list);
 	spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
 
 	return 0;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
index c1fbb2a..1b5fd9f 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
@@ -22,7 +22,7 @@
 		return -EINVAL;
 
 	CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
-	writel_relaxed(data, addr);
+	writel_relaxed_no_log(data, addr);
 
 	return 0;
 }
@@ -35,7 +35,7 @@
 	CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
 	/* Ensure previous writes are done */
 	wmb();
-	writel_relaxed(data, addr);
+	writel_relaxed_no_log(data, addr);
 
 	return 0;
 }
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index c85d255..8eef152 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -198,6 +198,7 @@
 	u32 offset;
 	u32 len;
 	enum sde_rot_regdump_access access;
+	u32 value;
 };
 
 struct sde_rot_lut_cfg {
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index fb74dab..916f978 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -422,7 +422,12 @@
 		head = &regdump[i];
 
 		if (head->access == SDE_ROT_REGDUMP_WRITE) {
-			writel_relaxed(1, mdata->sde_io.base + head->offset);
+			if (head->len != 1) {
+				SDEROT_ERR("invalid write len %u\n", head->len);
+				continue;
+			}
+			writel_relaxed(head->value,
+					mdata->sde_io.base + head->offset);
 			/* Make sure write go through */
 			wmb();
 		} else {
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index c94830a..7c36934 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -538,13 +538,13 @@
 	 * REGDMA RAM should be dump at last.
 	 */
 	{ "SDEROT_REGDMA_RESET", ROTTOP_SW_RESET_OVERRIDE, 1,
-		SDE_ROT_REGDUMP_WRITE },
+		SDE_ROT_REGDUMP_WRITE, 1 },
 	{ "SDEROT_REGDMA_RAM", SDE_ROT_REGDMA_RAM_OFFSET, 0x2000,
 		SDE_ROT_REGDUMP_READ },
 	{ "SDEROT_VBIF_NRT", SDE_ROT_VBIF_NRT_OFFSET, 0x590,
 		SDE_ROT_REGDUMP_VBIF },
-	{ "SDEROT_REGDMA_RESET", ROTTOP_SW_RESET_OVERRIDE, 0,
-		SDE_ROT_REGDUMP_WRITE },
+	{ "SDEROT_REGDMA_RESET", ROTTOP_SW_RESET_OVERRIDE, 1,
+		SDE_ROT_REGDUMP_WRITE, 0 },
 };
 
 struct sde_rot_cdp_params {
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index a1ae681..3f7e7bb 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1732,7 +1732,7 @@
 		if (ptr_svc->svc.listener_id != lstnr) {
 			pr_warn("Service requested does not exist\n");
 			__qseecom_qseos_fail_return_resp_tz(data, resp,
-					&send_data_rsp, ptr_svc, lstnr);
+					&send_data_rsp, NULL, lstnr);
 			return -ERESTARTSYS;
 		}
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 7df312e..e20ddba 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -2728,6 +2728,26 @@
 EXPORT_SYMBOL(ipa_start_gsi_channel);
 
 /**
+* ipa_is_vlan_mode - check if a LAN driver should load in VLAN mode
+* @iface - type of vlan capable device
+* @res - query result: true for vlan mode, false for non vlan mode
+*
+* API must be called after ipa_is_ready() returns true, otherwise it will fail
+*
+* Returns: 0 on success, negative on failure
+*/
+int ipa_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res)
+{
+	int ret;
+
+	IPA_API_DISPATCH_RETURN(ipa_is_vlan_mode, iface, res);
+
+	return ret;
+
+}
+EXPORT_SYMBOL(ipa_is_vlan_mode);
+
+/**
  * ipa_get_version_string() - Get string representation of IPA version
  * @ver: IPA version
  *
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 0779f34..f3e62b8 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -420,6 +420,7 @@
 
 	int (*ipa_get_smmu_params)(struct ipa_smmu_in_params *in,
 		struct ipa_smmu_out_params *out);
+	int (*ipa_is_vlan_mode)(enum ipa_vlan_ifaces iface, bool *res);
 };
 
 #ifdef CONFIG_IPA
diff --git a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
index 2975192..eadd58b 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
@@ -12,6 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/errno.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
@@ -123,6 +124,7 @@
  * @ipa_rm_resource_name_prod: IPA resource manager producer resource
  * @ipa_rm_resource_name_cons: IPA resource manager consumer resource
  * @pm_hdl: handle for IPA PM
+ * @is_vlan_mode: does the driver need to work in VLAN mode?
  */
 struct ecm_ipa_dev {
 	struct net_device *net;
@@ -141,6 +143,7 @@
 	enum ipa_rm_resource_name ipa_rm_resource_name_prod;
 	enum ipa_rm_resource_name ipa_rm_resource_name_cons;
 	u32 pm_hdl;
+	bool is_vlan_mode;
 };
 
 static int ecm_ipa_open(struct net_device *net);
@@ -173,7 +176,8 @@
 	(struct file *file, char __user *ubuf, size_t count, loff_t *ppos);
 static void ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx);
 static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *ecm_ipa_ctx);
-static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl);
+static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl,
+	bool is_vlan_mode);
 static int ecm_ipa_set_device_ethernet_addr
 	(u8 *dev_ethaddr, u8 device_ethaddr[]);
 static enum ecm_ipa_state ecm_ipa_next_state
@@ -283,6 +287,12 @@
 	}
 	ECM_IPA_DEBUG("Device Ethernet address set %pM\n", net->dev_addr);
 
+	if (ipa_is_vlan_mode(IPA_VLAN_IF_ECM, &ecm_ipa_ctx->is_vlan_mode)) {
+		ECM_IPA_ERROR("couldn't acquire vlan mode, is ipa ready?\n");
+		goto fail_get_vlan_mode;
+	}
+	ECM_IPA_DEBUG("is vlan mode %d\n", ecm_ipa_ctx->is_vlan_mode);
+
 	result = ecm_ipa_rules_cfg
 		(ecm_ipa_ctx, params->host_ethaddr, params->device_ethaddr);
 	if (result) {
@@ -319,8 +329,9 @@
 
 fail_register_netdev:
 	ecm_ipa_rules_destroy(ecm_ipa_ctx);
-fail_set_device_ethernet:
 fail_rules_cfg:
+fail_get_vlan_mode:
+fail_set_device_ethernet:
 	ecm_ipa_debugfs_destroy(ecm_ipa_ctx);
 fail_netdev_priv:
 	free_netdev(net);
@@ -450,7 +461,8 @@
 	}
 	ECM_IPA_DEBUG("ecm_ipa 2 Tx and 2 Rx properties were registered\n");
 
-	retval = ecm_ipa_ep_registers_cfg(usb_to_ipa_hdl, ipa_to_usb_hdl);
+	retval = ecm_ipa_ep_registers_cfg(usb_to_ipa_hdl, ipa_to_usb_hdl,
+		ecm_ipa_ctx->is_vlan_mode);
 	if (retval) {
 		ECM_IPA_ERROR("fail on ep cfg\n");
 		goto fail;
@@ -606,6 +618,10 @@
 		goto out;
 	}
 
+	if (ecm_ipa_ctx->is_vlan_mode)
+		if (unlikely(skb->protocol != ETH_P_8021Q))
+			ECM_IPA_DEBUG("ether_type != ETH_P_8021Q && vlan\n");
+
 	ret = ipa_tx_dp(ecm_ipa_ctx->ipa_to_usb_client, skb, NULL);
 	if (ret) {
 		ECM_IPA_ERROR("ipa transmit failed (%d)\n", ret);
@@ -843,6 +859,41 @@
 	ECM_IPA_DEBUG("queue started\n");
 }
 
+static void ecm_ipa_prepare_header_insertion(
+	int eth_type,
+	const char *hdr_name, struct ipa_hdr_add *add_hdr,
+	const void *dst_mac, const void *src_mac, bool is_vlan_mode)
+{
+	struct ethhdr *eth_hdr;
+	struct vlan_ethhdr *eth_vlan_hdr;
+
+	ECM_IPA_LOG_ENTRY();
+
+	add_hdr->is_partial = 0;
+	strlcpy(add_hdr->name, hdr_name, IPA_RESOURCE_NAME_MAX);
+	add_hdr->is_eth2_ofst_valid = true;
+	add_hdr->eth2_ofst = 0;
+
+	if (is_vlan_mode) {
+		eth_vlan_hdr = (struct vlan_ethhdr *)add_hdr->hdr;
+		memcpy(eth_vlan_hdr->h_dest, dst_mac, ETH_ALEN);
+		memcpy(eth_vlan_hdr->h_source, src_mac, ETH_ALEN);
+		eth_vlan_hdr->h_vlan_encapsulated_proto =
+			htons(eth_type);
+		eth_vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
+		add_hdr->hdr_len = VLAN_ETH_HLEN;
+		add_hdr->type = IPA_HDR_L2_802_1Q;
+	} else {
+		eth_hdr = (struct ethhdr *)add_hdr->hdr;
+		memcpy(eth_hdr->h_dest, dst_mac, ETH_ALEN);
+		memcpy(eth_hdr->h_source, src_mac, ETH_ALEN);
+		eth_hdr->h_proto = htons(eth_type);
+		add_hdr->hdr_len = ETH_HLEN;
+		add_hdr->type = IPA_HDR_L2_ETHERNET_II;
+	}
+	ECM_IPA_LOG_EXIT();
+}
+
 /**
  * ecm_ipa_rules_cfg() - set header insertion and register Tx/Rx properties
  *				Headers will be committed to HW
@@ -859,8 +910,6 @@
 	struct ipa_ioc_add_hdr *hdrs;
 	struct ipa_hdr_add *ipv4_hdr;
 	struct ipa_hdr_add *ipv6_hdr;
-	struct ethhdr *eth_ipv4;
-	struct ethhdr *eth_ipv6;
 	int result = 0;
 
 	ECM_IPA_LOG_ENTRY();
@@ -871,28 +920,17 @@
 		result = -ENOMEM;
 		goto out;
 	}
+
 	ipv4_hdr = &hdrs->hdr[0];
-	eth_ipv4 = (struct ethhdr *)ipv4_hdr->hdr;
+	ecm_ipa_prepare_header_insertion(
+		ETH_P_IP, ECM_IPA_IPV4_HDR_NAME,
+		ipv4_hdr, dst_mac, src_mac, ecm_ipa_ctx->is_vlan_mode);
+
 	ipv6_hdr = &hdrs->hdr[1];
-	eth_ipv6 = (struct ethhdr *)ipv6_hdr->hdr;
-	strlcpy(ipv4_hdr->name, ECM_IPA_IPV4_HDR_NAME, IPA_RESOURCE_NAME_MAX);
-	memcpy(eth_ipv4->h_dest, dst_mac, ETH_ALEN);
-	memcpy(eth_ipv4->h_source, src_mac, ETH_ALEN);
-	eth_ipv4->h_proto = htons(ETH_P_IP);
-	ipv4_hdr->hdr_len = ETH_HLEN;
-	ipv4_hdr->is_partial = 0;
-	ipv4_hdr->is_eth2_ofst_valid = true;
-	ipv4_hdr->eth2_ofst = 0;
-	ipv4_hdr->type = IPA_HDR_L2_ETHERNET_II;
-	strlcpy(ipv6_hdr->name, ECM_IPA_IPV6_HDR_NAME, IPA_RESOURCE_NAME_MAX);
-	memcpy(eth_ipv6->h_dest, dst_mac, ETH_ALEN);
-	memcpy(eth_ipv6->h_source, src_mac, ETH_ALEN);
-	eth_ipv6->h_proto = htons(ETH_P_IPV6);
-	ipv6_hdr->hdr_len = ETH_HLEN;
-	ipv6_hdr->is_partial = 0;
-	ipv6_hdr->is_eth2_ofst_valid = true;
-	ipv6_hdr->eth2_ofst = 0;
-	ipv6_hdr->type = IPA_HDR_L2_ETHERNET_II;
+	ecm_ipa_prepare_header_insertion(
+		ETH_P_IPV6, ECM_IPA_IPV6_HDR_NAME,
+		ipv6_hdr, dst_mac, src_mac, ecm_ipa_ctx->is_vlan_mode);
+
 	hdrs->commit = 1;
 	hdrs->num_hdrs = 2;
 	result = ipa_add_hdr(hdrs);
@@ -972,10 +1010,14 @@
 	struct ipa_rx_intf rx_properties = {0};
 	struct ipa_ioc_rx_intf_prop *rx_ipv4_property;
 	struct ipa_ioc_rx_intf_prop *rx_ipv6_property;
+	enum ipa_hdr_l2_type hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
 	int result = 0;
 
 	ECM_IPA_LOG_ENTRY();
 
+	if (ecm_ipa_ctx->is_vlan_mode)
+		hdr_l2_type = IPA_HDR_L2_802_1Q;
+
 	tx_properties.prop = properties;
 	ipv4_property = &tx_properties.prop[0];
 	ipv4_property->ip = IPA_IP_v4;
@@ -983,11 +1025,11 @@
 	strlcpy
 		(ipv4_property->hdr_name, ECM_IPA_IPV4_HDR_NAME,
 		IPA_RESOURCE_NAME_MAX);
-	ipv4_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	ipv4_property->hdr_l2_type = hdr_l2_type;
 	ipv6_property = &tx_properties.prop[1];
 	ipv6_property->ip = IPA_IP_v6;
 	ipv6_property->dst_pipe = ecm_ipa_ctx->ipa_to_usb_client;
-	ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	ipv6_property->hdr_l2_type = hdr_l2_type;
 	strlcpy
 		(ipv6_property->hdr_name, ECM_IPA_IPV6_HDR_NAME,
 		IPA_RESOURCE_NAME_MAX);
@@ -998,12 +1040,12 @@
 	rx_ipv4_property->ip = IPA_IP_v4;
 	rx_ipv4_property->attrib.attrib_mask = 0;
 	rx_ipv4_property->src_pipe = ecm_ipa_ctx->usb_to_ipa_client;
-	rx_ipv4_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	rx_ipv4_property->hdr_l2_type = hdr_l2_type;
 	rx_ipv6_property = &rx_properties.prop[1];
 	rx_ipv6_property->ip = IPA_IP_v6;
 	rx_ipv6_property->attrib.attrib_mask = 0;
 	rx_ipv6_property->src_pipe = ecm_ipa_ctx->usb_to_ipa_client;
-	rx_ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	rx_ipv6_property->hdr_l2_type = hdr_l2_type;
 	rx_properties.num_props = 2;
 
 	result = ipa_register_intf("ecm0", &tx_properties, &rx_properties);
@@ -1336,6 +1378,13 @@
 		goto fail_file;
 	}
 
+	file = debugfs_create_bool("is_vlan_mode", flags_read_only,
+		ecm_ipa_ctx->directory, &ecm_ipa_ctx->is_vlan_mode);
+	if (!file) {
+		ECM_IPA_ERROR("could not create is_vlan_mode file\n");
+		goto fail_file;
+	}
+
 	ECM_IPA_DEBUG("debugfs entries were created\n");
 	ECM_IPA_LOG_EXIT();
 
@@ -1362,8 +1411,9 @@
 /**
  * ecm_ipa_ep_cfg() - configure the USB endpoints for ECM
  *
- *usb_to_ipa_hdl: handle received from ipa_connect
- *ipa_to_usb_hdl: handle received from ipa_connect
+ * @usb_to_ipa_hdl: handle received from ipa_connect
+ * @ipa_to_usb_hdl: handle received from ipa_connect
+ * @is_vlan_mode - should driver work in vlan mode?
  *
  * USB to IPA pipe:
  *  - No de-aggregation
@@ -1374,16 +1424,21 @@
  *  - No aggregation
  *  - Add Ethernet header
  */
-static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl)
+static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl,
+	bool is_vlan_mode)
 {
 	int result = 0;
 	struct ipa_ep_cfg usb_to_ipa_ep_cfg;
 	struct ipa_ep_cfg ipa_to_usb_ep_cfg;
+	uint8_t hdr_add = 0;
+
 
 	ECM_IPA_LOG_ENTRY();
+	if (is_vlan_mode)
+		hdr_add = VLAN_HLEN;
 	memset(&usb_to_ipa_ep_cfg, 0, sizeof(struct ipa_ep_cfg));
 	usb_to_ipa_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR;
-	usb_to_ipa_ep_cfg.hdr.hdr_len = ETH_HLEN;
+	usb_to_ipa_ep_cfg.hdr.hdr_len = ETH_HLEN + hdr_add;
 	usb_to_ipa_ep_cfg.nat.nat_en = IPA_SRC_NAT;
 	usb_to_ipa_ep_cfg.route.rt_tbl_hdl = 0;
 	usb_to_ipa_ep_cfg.mode.dst = IPA_CLIENT_A5_LAN_WAN_CONS;
@@ -1395,7 +1450,7 @@
 	}
 	memset(&ipa_to_usb_ep_cfg, 0, sizeof(struct ipa_ep_cfg));
 	ipa_to_usb_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR;
-	ipa_to_usb_ep_cfg.hdr.hdr_len = ETH_HLEN;
+	ipa_to_usb_ep_cfg.hdr.hdr_len = ETH_HLEN + hdr_add;
 	ipa_to_usb_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
 	result = ipa_cfg_ep(ipa_to_usb_hdl, &ipa_to_usb_ep_cfg);
 	if (result) {
diff --git a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
index 2e87bd2..4958c69 100644
--- a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
@@ -12,6 +12,7 @@
 #include <linux/atomic.h>
 #include <linux/errno.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/debugfs.h>
 #include <linux/in.h>
 #include <linux/stddef.h>
@@ -162,6 +163,7 @@
  * @xmit_error_delayed_work: work item for cases where IPA driver Tx fails
  * @state_lock: used to protect the state variable.
  * @pm_hdl: handle for IPA PM framework
+ * @is_vlan_mode: should driver work in vlan mode?
  */
 struct rndis_ipa_dev {
 	struct net_device *net;
@@ -191,6 +193,7 @@
 	struct delayed_work xmit_error_delayed_work;
 	spinlock_t state_lock; /* Spinlock for the state variable.*/
 	u32 pm_hdl;
+	bool is_vlan_mode;
 };
 
 /**
@@ -217,19 +220,20 @@
 static void rndis_ipa_tx_timeout(struct net_device *net);
 static int rndis_ipa_stop(struct net_device *net);
 static void rndis_ipa_enable_data_path(struct rndis_ipa_dev *rndis_ipa_ctx);
-static struct sk_buff *rndis_encapsulate_skb(struct sk_buff *skb);
+static struct sk_buff *rndis_encapsulate_skb(struct sk_buff *skb,
+	struct rndis_ipa_dev *rndis_ipa_ctx);
 static void rndis_ipa_xmit_error(struct sk_buff *skb);
 static void rndis_ipa_xmit_error_aftercare_wq(struct work_struct *work);
 static void rndis_ipa_prepare_header_insertion
 	(int eth_type,
 	const char *hdr_name, struct ipa_hdr_add *add_hdr,
-	const void *dst_mac, const void *src_mac);
+	const void *dst_mac, const void *src_mac, bool is_vlan_mode);
 static int rndis_ipa_hdrs_cfg
 	(struct rndis_ipa_dev *rndis_ipa_ctx,
 	const void *dst_mac, const void *src_mac);
 static int rndis_ipa_hdrs_destroy(struct rndis_ipa_dev *rndis_ipa_ctx);
 static struct net_device_stats *rndis_ipa_get_stats(struct net_device *net);
-static int rndis_ipa_register_properties(char *netdev_name);
+static int rndis_ipa_register_properties(char *netdev_name, bool is_vlan_mode);
 static int rndis_ipa_deregister_properties(char *netdev_name);
 static void rndis_ipa_rm_notify
 	(void *user_data, enum ipa_rm_event event,
@@ -262,7 +266,8 @@
 	(u32 usb_to_ipa_hdl,
 	u32 ipa_to_usb_hdl, u32 max_xfer_size_bytes_to_dev,
 	u32 max_xfer_size_bytes_to_host, u32 mtu,
-	bool deaggr_enable);
+	bool deaggr_enable,
+	bool is_vlan_mode);
 static int rndis_ipa_set_device_ethernet_addr
 	(u8 *dev_ethaddr,
 	u8 device_ethaddr[]);
@@ -566,6 +571,14 @@
 	}
 	RNDIS_IPA_DEBUG("Device Ethernet address set %pM\n", net->dev_addr);
 
+	if (ipa_is_vlan_mode(IPA_VLAN_IF_RNDIS,
+		&rndis_ipa_ctx->is_vlan_mode)) {
+		RNDIS_IPA_ERROR("couldn't acquire vlan mode, is ipa ready?\n");
+		goto fail_get_vlan_mode;
+	}
+
+	RNDIS_IPA_DEBUG("is_vlan_mode %d\n", rndis_ipa_ctx->is_vlan_mode);
+
 	result = rndis_ipa_hdrs_cfg
 			(rndis_ipa_ctx,
 			params->host_ethaddr,
@@ -576,7 +589,8 @@
 	}
 	RNDIS_IPA_DEBUG("IPA header-insertion configed for Ethernet+RNDIS\n");
 
-	result = rndis_ipa_register_properties(net->name);
+	result = rndis_ipa_register_properties(net->name,
+		rndis_ipa_ctx->is_vlan_mode);
 	if (result) {
 		RNDIS_IPA_ERROR("fail on properties set\n");
 		goto fail_register_tx;
@@ -612,8 +626,9 @@
 	rndis_ipa_deregister_properties(net->name);
 fail_register_tx:
 	rndis_ipa_hdrs_destroy(rndis_ipa_ctx);
-fail_set_device_ethernet:
 fail_hdrs_cfg:
+fail_get_vlan_mode:
+fail_set_device_ethernet:
 	rndis_ipa_debugfs_destroy(rndis_ipa_ctx);
 fail_netdev_priv:
 	free_netdev(net);
@@ -728,7 +743,8 @@
 		max_xfer_size_bytes_to_dev,
 		max_xfer_size_bytes_to_host,
 		rndis_ipa_ctx->net->mtu,
-		rndis_ipa_ctx->deaggregation_enable);
+		rndis_ipa_ctx->deaggregation_enable,
+		rndis_ipa_ctx->is_vlan_mode);
 	if (result) {
 		RNDIS_IPA_ERROR("fail on ep cfg\n");
 		goto fail;
@@ -910,7 +926,7 @@
 		goto out;
 	}
 
-	skb = rndis_encapsulate_skb(skb);
+	skb = rndis_encapsulate_skb(skb, rndis_ipa_ctx);
 	trace_rndis_tx_dp(skb->protocol);
 	ret = ipa_tx_dp(IPA_TO_USB_CLIENT, skb, NULL);
 	if (ret) {
@@ -1456,6 +1472,7 @@
  *  for IPA->USB pipe
  * src_mac: device MAC (Ethernet) address to be added to packets
  *  for IPA->USB pipe
+ * is_vlan_mode: should driver work in vlan mode?
  *
  * This function shall build the header-insertion block request for a
  * single Ethernet+RNDIS header)
@@ -1468,23 +1485,37 @@
 static void rndis_ipa_prepare_header_insertion(
 	int eth_type,
 	const char *hdr_name, struct ipa_hdr_add *add_hdr,
-	const void *dst_mac, const void *src_mac)
+	const void *dst_mac, const void *src_mac, bool is_vlan_mode)
 {
 	struct ethhdr *eth_hdr;
+	struct vlan_ethhdr *eth_vlan_hdr;
 
 	add_hdr->hdr_len = sizeof(rndis_template_hdr);
 	add_hdr->is_partial = false;
 	strlcpy(add_hdr->name, hdr_name, IPA_RESOURCE_NAME_MAX);
 
 	memcpy(add_hdr->hdr, &rndis_template_hdr, sizeof(rndis_template_hdr));
-	eth_hdr = (struct ethhdr *)(add_hdr->hdr + sizeof(rndis_template_hdr));
-	memcpy(eth_hdr->h_dest, dst_mac, ETH_ALEN);
-	memcpy(eth_hdr->h_source, src_mac, ETH_ALEN);
-	eth_hdr->h_proto = htons(eth_type);
-	add_hdr->hdr_len += ETH_HLEN;
 	add_hdr->is_eth2_ofst_valid = true;
 	add_hdr->eth2_ofst = sizeof(rndis_template_hdr);
-	add_hdr->type = IPA_HDR_L2_ETHERNET_II;
+
+	if (is_vlan_mode) {
+		eth_vlan_hdr = (struct vlan_ethhdr *)(add_hdr->hdr +
+			sizeof(rndis_template_hdr));
+		memcpy(eth_vlan_hdr->h_dest, dst_mac, ETH_ALEN);
+		memcpy(eth_vlan_hdr->h_source, src_mac, ETH_ALEN);
+		eth_vlan_hdr->h_vlan_encapsulated_proto = htons(eth_type);
+		eth_vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
+		add_hdr->hdr_len += VLAN_ETH_HLEN;
+		add_hdr->type = IPA_HDR_L2_802_1Q;
+	} else {
+		eth_hdr = (struct ethhdr *)(add_hdr->hdr +
+			sizeof(rndis_template_hdr));
+		memcpy(eth_hdr->h_dest, dst_mac, ETH_ALEN);
+		memcpy(eth_hdr->h_source, src_mac, ETH_ALEN);
+		eth_hdr->h_proto = htons(eth_type);
+		add_hdr->hdr_len += ETH_HLEN;
+		add_hdr->type = IPA_HDR_L2_ETHERNET_II;
+	}
 }
 
 /**
@@ -1526,10 +1557,10 @@
 	ipv6_hdr = &hdrs->hdr[1];
 	rndis_ipa_prepare_header_insertion
 		(ETH_P_IP, IPV4_HDR_NAME,
-		ipv4_hdr, dst_mac, src_mac);
+		ipv4_hdr, dst_mac, src_mac, rndis_ipa_ctx->is_vlan_mode);
 	rndis_ipa_prepare_header_insertion
 		(ETH_P_IPV6, IPV6_HDR_NAME,
-		ipv6_hdr, dst_mac, src_mac);
+		ipv6_hdr, dst_mac, src_mac, rndis_ipa_ctx->is_vlan_mode);
 
 	hdrs->commit = 1;
 	hdrs->num_hdrs = 2;
@@ -1610,6 +1641,7 @@
  * rndis_ipa_register_properties() - set Tx/Rx properties needed
  *  by IPA configuration manager
  * @netdev_name: a string with the name of the network interface device
+ * @is_vlan_mode: should driver work in vlan mode?
  *
  * Register Tx/Rx properties to allow user space configuration (IPA
  * Configuration Manager):
@@ -1628,7 +1660,7 @@
  *   This rules shall be added based on the attribute mask supplied at
  *   this function, that is, always hit rule.
  */
-static int rndis_ipa_register_properties(char *netdev_name)
+static int rndis_ipa_register_properties(char *netdev_name, bool is_vlan_mode)
 {
 	struct ipa_tx_intf tx_properties = {0};
 	struct ipa_ioc_tx_intf_prop properties[2] = { {0}, {0} };
@@ -1638,10 +1670,14 @@
 	struct ipa_rx_intf rx_properties = {0};
 	struct ipa_ioc_rx_intf_prop *rx_ipv4_property;
 	struct ipa_ioc_rx_intf_prop *rx_ipv6_property;
+	enum ipa_hdr_l2_type hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
 	int result = 0;
 
 	RNDIS_IPA_LOG_ENTRY();
 
+	if (is_vlan_mode)
+		hdr_l2_type = IPA_HDR_L2_802_1Q;
+
 	tx_properties.prop = properties;
 	ipv4_property = &tx_properties.prop[0];
 	ipv4_property->ip = IPA_IP_v4;
@@ -1649,14 +1685,14 @@
 	strlcpy
 		(ipv4_property->hdr_name, IPV4_HDR_NAME,
 		IPA_RESOURCE_NAME_MAX);
-	ipv4_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	ipv4_property->hdr_l2_type = hdr_l2_type;
 	ipv6_property = &tx_properties.prop[1];
 	ipv6_property->ip = IPA_IP_v6;
 	ipv6_property->dst_pipe = IPA_TO_USB_CLIENT;
 	strlcpy
 		(ipv6_property->hdr_name, IPV6_HDR_NAME,
 		IPA_RESOURCE_NAME_MAX);
-	ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	ipv6_property->hdr_l2_type = hdr_l2_type;
 	tx_properties.num_props = 2;
 
 	rx_properties.prop = rx_ioc_properties;
@@ -1664,12 +1700,12 @@
 	rx_ipv4_property->ip = IPA_IP_v4;
 	rx_ipv4_property->attrib.attrib_mask = 0;
 	rx_ipv4_property->src_pipe = IPA_CLIENT_USB_PROD;
-	rx_ipv4_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	rx_ipv4_property->hdr_l2_type = hdr_l2_type;
 	rx_ipv6_property = &rx_properties.prop[1];
 	rx_ipv6_property->ip = IPA_IP_v6;
 	rx_ipv6_property->attrib.attrib_mask = 0;
 	rx_ipv6_property->src_pipe = IPA_CLIENT_USB_PROD;
-	rx_ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	rx_ipv6_property->hdr_l2_type = hdr_l2_type;
 	rx_properties.num_props = 2;
 
 	result = ipa_register_intf("rndis0", &tx_properties, &rx_properties);
@@ -1948,12 +1984,14 @@
  * rndis_encapsulate_skb() - encapsulate the given Ethernet skb with
  *  an RNDIS header
  * @skb: packet to be encapsulated with the RNDIS header
+ * @rndis_ipa_ctx: main driver context
  *
  * Shall use a template header for RNDIS and update it with the given
  * skb values.
  * Ethernet is expected to be already encapsulate the packet.
  */
-static struct sk_buff *rndis_encapsulate_skb(struct sk_buff *skb)
+static struct sk_buff *rndis_encapsulate_skb(struct sk_buff *skb,
+	struct rndis_ipa_dev *rndis_ipa_ctx)
 {
 	struct rndis_pkt_hdr *rndis_hdr;
 	int payload_byte_len = skb->len;
@@ -1971,6 +2009,10 @@
 		skb = new_skb;
 	}
 
+	if (rndis_ipa_ctx->is_vlan_mode)
+		if (unlikely(skb->protocol != ETH_P_8021Q))
+			RNDIS_IPA_DEBUG("ether_type != ETH_P_8021Q && vlan\n");
+
 	/* make room at the head of the SKB to put the RNDIS header */
 	rndis_hdr = (struct rndis_pkt_hdr *)skb_push(skb,
 					sizeof(rndis_template_hdr));
@@ -2046,6 +2088,8 @@
  * @max_xfer_size_bytes_to_host: the maximum size, in bytes, that the host
  *  expects to receive from the device. supplied on REMOTE_NDIS_INITIALIZE_MSG.
  * @mtu: the netdev MTU size, in bytes
+ * @deaggr_enable: should deaggregation be enabled?
+ * @is_vlan_mode: should driver work in vlan mode?
  *
  * USB to IPA pipe:
  *  - de-aggregation
@@ -2064,7 +2108,8 @@
 	u32 max_xfer_size_bytes_to_dev,
 	u32 max_xfer_size_bytes_to_host,
 	u32 mtu,
-	bool deaggr_enable)
+	bool deaggr_enable,
+	bool is_vlan_mode)
 {
 	int result;
 	struct ipa_ep_cfg *usb_to_ipa_ep_cfg;
@@ -2077,6 +2122,20 @@
 		RNDIS_IPA_DEBUG("deaggregation disabled\n");
 	}
 
+	if (is_vlan_mode) {
+		usb_to_ipa_ep_cfg->hdr.hdr_len =
+			VLAN_ETH_HLEN + sizeof(struct rndis_pkt_hdr);
+		ipa_to_usb_ep_cfg.hdr.hdr_len =
+			VLAN_ETH_HLEN + sizeof(struct rndis_pkt_hdr);
+		ipa_to_usb_ep_cfg.hdr.hdr_additional_const_len = VLAN_ETH_HLEN;
+	} else {
+		usb_to_ipa_ep_cfg->hdr.hdr_len =
+			ETH_HLEN + sizeof(struct rndis_pkt_hdr);
+		ipa_to_usb_ep_cfg.hdr.hdr_len =
+			ETH_HLEN + sizeof(struct rndis_pkt_hdr);
+		ipa_to_usb_ep_cfg.hdr.hdr_additional_const_len = ETH_HLEN;
+	}
+
 	usb_to_ipa_ep_cfg->deaggr.max_packet_len = max_xfer_size_bytes_to_dev;
 	result = ipa_cfg_ep(usb_to_ipa_hdl, usb_to_ipa_ep_cfg);
 	if (result) {
@@ -2452,6 +2511,14 @@
 		goto fail_file;
 	}
 
+	file = debugfs_create_bool("is_vlan_mode", flags_read_only,
+		rndis_ipa_ctx->directory,
+		&rndis_ipa_ctx->is_vlan_mode);
+	if (!file) {
+		RNDIS_IPA_ERROR("fail to create is_vlan_mode file\n");
+		goto fail_file;
+	}
+
 	RNDIS_IPA_DEBUG("debugfs entries were created\n");
 	RNDIS_IPA_LOG_EXIT();
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index af4d448..57b988b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -3855,6 +3855,9 @@
 {
 	u32 clk_rate;
 
+	if (!ipa3_ctx->enable_clock_scaling)
+		return 0;
+
 	IPADBG_LOW("idx = %d\n", idx);
 
 	if (idx <= 0 || idx >= ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases) {
@@ -3863,10 +3866,12 @@
 	}
 
 	if (idx == 1)
-		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_svs;
+		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_svs2;
 	else if (idx == 2)
-		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_nominal;
+		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_svs;
 	else if (idx == 3)
+		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_nominal;
+	else if (idx == 4)
 		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_turbo;
 	else {
 		IPAERR("bad voltage\n");
@@ -4633,7 +4638,7 @@
 {
 	unsigned long missing;
 
-	char dbg_buff[16] = { 0 };
+	char dbg_buff[32] = { 0 };
 
 	if (sizeof(dbg_buff) < count + 1)
 		return -EFAULT;
@@ -4646,7 +4651,9 @@
 	}
 
 	if (count > 0)
-		dbg_buff[count - 1] = '\0';
+		dbg_buff[count] = '\0';
+
+	IPADBG("user input string %s\n", dbg_buff);
 
 	/* Prevent consequent calls from trying to load the FW again. */
 	if (ipa3_is_ready())
@@ -4654,13 +4661,36 @@
 
 	/* Check MHI configuration on MDM devices */
 	if (!ipa3_is_msm_device()) {
+
+		if (strnstr(dbg_buff, "vlan", strlen(dbg_buff))) {
+			if (strnstr(dbg_buff, "eth", strlen(dbg_buff)))
+				ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_EMAC] =
+				true;
+			if (strnstr(dbg_buff, "rndis", strlen(dbg_buff)))
+				ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_RNDIS] =
+				true;
+			if (strnstr(dbg_buff, "ecm", strlen(dbg_buff)))
+				ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_ECM] =
+				true;
+
+			/*
+			 * when vlan mode is passed to our dev we expect
+			 * another write
+			 */
+			return count;
+		}
+
 		if (!strcasecmp(dbg_buff, "MHI")) {
 			ipa3_ctx->ipa_config_is_mhi = true;
 			pr_info(
-			"IPA is loading with MHI configuration\n");
-		} else {
+				"IPA is loading with MHI configuration\n");
+		} else if (!strcmp(dbg_buff, "1\n")) {
 			pr_info(
-			"IPA is loading with non MHI configuration\n");
+				"IPA is loading with non MHI configuration\n");
+		} else {
+			IPAERR("got invalid string %s not loading FW\n",
+				dbg_buff);
+			return count;
 		}
 	}
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index adbd7b8..d7d74a3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1373,6 +1373,7 @@
 	int num_ipa_cne_evt_req;
 	struct mutex ipa_cne_evt_lock;
 	bool use_ipa_pm;
+	bool vlan_mode_iface[IPA_VLAN_IF_MAX];
 };
 
 struct ipa3_plat_drv_res {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
index 3bf0327..be342cb 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
@@ -1030,8 +1030,9 @@
 				client->state);
 			spin_unlock_irqrestore(&client->state_lock, flags);
 		} else if (client->state ==
-			IPA_PM_ACTIVATED_PENDING_DEACTIVATION ||
-			IPA_PM_ACTIVATED_PENDING_RESCHEDULE) {
+				IPA_PM_ACTIVATED_PENDING_DEACTIVATION ||
+			client->state ==
+				IPA_PM_ACTIVATED_PENDING_RESCHEDULE) {
 			run_algorithm = true;
 			client->state = IPA_PM_DEACTIVATED;
 			IPA_PM_DBG_STATE(client->hdl, client->name,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 86d50f6..6a5e85b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4318,6 +4318,38 @@
 	ipa3_ctx->tag_process_before_gating = val;
 }
 
+/**
+ * ipa3_is_vlan_mode - check if a LAN driver should load in VLAN mode
+ * @iface - type of vlan capable device
+ * @res - query result: true for vlan mode, false for non vlan mode
+ *
+ * API must be called after ipa_is_ready() returns true, otherwise it will fail
+ *
+ * Returns: 0 on success, negative on failure
+ */
+static int ipa3_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res)
+{
+	if (!res) {
+		IPAERR("NULL out param\n");
+		return -EINVAL;
+	}
+
+	if (iface < 0 || iface > IPA_VLAN_IF_MAX) {
+		IPAERR("invalid iface %d\n", iface);
+		return -EINVAL;
+	}
+
+	if (!ipa3_is_ready()) {
+		IPAERR("IPA is not ready yet\n");
+		return -ENODEV;
+	}
+
+	*res = ipa3_ctx->vlan_mode_iface[iface];
+
+	IPADBG("Driver %d vlan mode is %d\n", iface, *res);
+	return 0;
+}
+
 int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type,
 	struct ipa_api_controller *api_ctrl)
 {
@@ -4504,6 +4536,7 @@
 	api_ctrl->ipa_disable_wdi3_pipes = ipa3_disable_wdi3_pipes;
 	api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg;
 	api_ctrl->ipa_get_smmu_params = ipa3_get_smmu_params;
+	api_ctrl->ipa_is_vlan_mode = ipa3_is_vlan_mode;
 
 	return 0;
 }
@@ -4867,6 +4900,77 @@
 	}
 }
 
+static int __ipa3_stop_gsi_channel(u32 clnt_hdl)
+{
+	struct ipa_mem_buffer mem;
+	int res = 0;
+	int i;
+	struct ipa3_ep_context *ep;
+
+	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
+		ipa3_ctx->ep[clnt_hdl].valid == 0) {
+		IPAERR("bad parm.\n");
+		return -EINVAL;
+	}
+
+	ep = &ipa3_ctx->ep[clnt_hdl];
+	memset(&mem, 0, sizeof(mem));
+
+	if (IPA_CLIENT_IS_PROD(ep->client)) {
+		IPADBG("Calling gsi_stop_channel ch:%lu\n",
+			ep->gsi_chan_hdl);
+		res = gsi_stop_channel(ep->gsi_chan_hdl);
+		IPADBG("gsi_stop_channel ch: %lu returned %d\n",
+			ep->gsi_chan_hdl, res);
+		return res;
+	}
+
+	for (i = 0; i < IPA_GSI_CHANNEL_STOP_MAX_RETRY; i++) {
+		IPADBG("Calling gsi_stop_channel ch:%lu\n",
+			ep->gsi_chan_hdl);
+		res = gsi_stop_channel(ep->gsi_chan_hdl);
+		IPADBG("gsi_stop_channel ch: %lu returned %d\n",
+			ep->gsi_chan_hdl, res);
+		if (res != -GSI_STATUS_AGAIN && res != -GSI_STATUS_TIMED_OUT)
+			return res;
+
+		IPADBG("Inject a DMA_TASK with 1B packet to IPA\n");
+		/* Send a 1B packet DMA_TASK to IPA and try again */
+		res = ipa3_inject_dma_task_for_gsi();
+		if (res) {
+			IPAERR("Failed to inject DMA TASk for GSI\n");
+			return res;
+		}
+
+		/* sleep for short period to flush IPA */
+		usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC,
+			IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC);
+	}
+
+	IPAERR("Failed  to stop GSI channel with retries\n");
+	return -EFAULT;
+}
+
+/**
+ * ipa3_stop_gsi_channel()- Stops a GSI channel in IPA
+ * @chan_hdl: GSI channel handle
+ *
+ * This function implements the sequence to stop a GSI channel
+ * in IPA. This function returns when the channel is in STOP state.
+ *
+ * Return value: 0 on success, negative otherwise
+ */
+int ipa3_stop_gsi_channel(u32 clnt_hdl)
+{
+	int res;
+
+	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl));
+	res = __ipa3_stop_gsi_channel(clnt_hdl);
+	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+	return res;
+}
+
 void ipa3_suspend_apps_pipes(bool suspend)
 {
 	struct ipa_ep_cfg_ctrl cfg;
@@ -4889,7 +4993,7 @@
 			ipa_ep_idx);
 		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
 			if (suspend) {
-				res = ipa3_stop_gsi_channel(ipa_ep_idx);
+				res = __ipa3_stop_gsi_channel(ipa_ep_idx);
 				if (res) {
 					IPAERR("failed to stop LAN channel\n");
 					ipa_assert();
@@ -4923,7 +5027,7 @@
 			ipa_ep_idx);
 		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
 			if (suspend) {
-				res = ipa3_stop_gsi_channel(ipa_ep_idx);
+				res = __ipa3_stop_gsi_channel(ipa_ep_idx);
 				if (res) {
 					IPAERR("failed to stop WAN channel\n");
 					ipa_assert();
@@ -5013,73 +5117,6 @@
 	return 0;
 }
 
-/**
- * ipa3_stop_gsi_channel()- Stops a GSI channel in IPA
- * @chan_hdl: GSI channel handle
- *
- * This function implements the sequence to stop a GSI channel
- * in IPA. This function returns when the channel is is STOP state.
- *
- * Return value: 0 on success, negative otherwise
- */
-int ipa3_stop_gsi_channel(u32 clnt_hdl)
-{
-	struct ipa_mem_buffer mem;
-	int res = 0;
-	int i;
-	struct ipa3_ep_context *ep;
-
-	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
-		ipa3_ctx->ep[clnt_hdl].valid == 0) {
-		IPAERR("bad parm.\n");
-		return -EINVAL;
-	}
-
-	ep = &ipa3_ctx->ep[clnt_hdl];
-
-	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl));
-
-	memset(&mem, 0, sizeof(mem));
-
-	if (IPA_CLIENT_IS_PROD(ep->client)) {
-		IPADBG("Calling gsi_stop_channel ch:%lu\n",
-			ep->gsi_chan_hdl);
-		res = gsi_stop_channel(ep->gsi_chan_hdl);
-		IPADBG("gsi_stop_channel ch: %lu returned %d\n",
-			ep->gsi_chan_hdl, res);
-		goto end_sequence;
-	}
-
-	for (i = 0; i < IPA_GSI_CHANNEL_STOP_MAX_RETRY; i++) {
-		IPADBG("Calling gsi_stop_channel ch:%lu\n",
-			ep->gsi_chan_hdl);
-		res = gsi_stop_channel(ep->gsi_chan_hdl);
-		IPADBG("gsi_stop_channel ch: %lu returned %d\n",
-			ep->gsi_chan_hdl, res);
-		if (res != -GSI_STATUS_AGAIN && res != -GSI_STATUS_TIMED_OUT)
-			goto end_sequence;
-
-		IPADBG("Inject a DMA_TASK with 1B packet to IPA\n");
-		/* Send a 1B packet DMA_TASK to IPA and try again */
-		res = ipa3_inject_dma_task_for_gsi();
-		if (res) {
-			IPAERR("Failed to inject DMA TASk for GSI\n");
-			goto end_sequence;
-		}
-
-		/* sleep for short period to flush IPA */
-		usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC,
-			IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC);
-	}
-
-	IPAERR("Failed  to stop GSI channel with retries\n");
-	res = -EFAULT;
-end_sequence:
-	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
-
-	return res;
-}
-
 static int ipa3_load_single_fw(const struct firmware *firmware,
 	const struct elf32_phdr *phdr)
 {
diff --git a/drivers/platform/msm/ipa/test/ipa_test_mhi.c b/drivers/platform/msm/ipa/test/ipa_test_mhi.c
index 98861de..195799e 100644
--- a/drivers/platform/msm/ipa/test/ipa_test_mhi.c
+++ b/drivers/platform/msm/ipa/test/ipa_test_mhi.c
@@ -612,7 +612,8 @@
 		p_events[ev_ring_idx].rp =
 			(u32)event_ring_bufs[ev_ring_idx].phys_base;
 		p_events[ev_ring_idx].wp =
-			(u32)event_ring_bufs[ev_ring_idx].phys_base;
+			(u32)event_ring_bufs[ev_ring_idx].phys_base +
+			event_ring_bufs[ev_ring_idx].size - 16;
 	} else {
 		IPA_UT_LOG("Skip configuring event ring - already done\n");
 	}
@@ -3261,11 +3262,11 @@
 	IPA_UT_ADD_TEST(suspend_resume_with_open_aggr,
 		"several suspend/resume iterations with open aggregation frame",
 		ipa_mhi_test_in_loop_suspend_resume_aggr_open,
-		true, IPA_HW_v3_0, IPA_HW_MAX),
+		true, IPA_HW_v3_0, IPA_HW_v3_5_1),
 	IPA_UT_ADD_TEST(force_suspend_resume_with_open_aggr,
 		"several force suspend/resume iterations with open aggregation frame",
 		ipa_mhi_test_in_loop_force_suspend_resume_aggr_open,
-		true, IPA_HW_v3_0, IPA_HW_MAX),
+		true, IPA_HW_v3_0, IPA_HW_v3_5_1),
 	IPA_UT_ADD_TEST(suspend_resume_with_host_wakeup,
 		"several suspend and host wakeup resume iterations",
 		ipa_mhi_test_in_loop_suspend_host_wakeup,
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 93121df..95e3782 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -321,10 +321,18 @@
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[pipe_connect->bam_type];
 	struct sps_mem_buffer *data_buf = &(pipe_connect->data_mem_buf);
 	struct sps_mem_buffer *desc_buf = &(pipe_connect->desc_mem_buf);
+	struct device *dev = &ctx->usb_bam_pdev->dev;
+	struct sg_table data_sgt, desc_sgt;
+	dma_addr_t data_iova, desc_iova;
+	u32 data_fifo_size;
 
 	pr_debug("%s: data_fifo size:%x desc_fifo_size:%x\n",
 				__func__, pipe_connect->data_fifo_size,
 				pipe_connect->desc_fifo_size);
+
+	if (dev->parent)
+		dev = dev->parent;
+
 	switch (pipe_connect->mem_type) {
 	case SPS_PIPE_MEM:
 		log_event_dbg("%s: USB BAM using SPS pipe memory\n", __func__);
@@ -366,7 +374,16 @@
 			ret = -ENOMEM;
 			goto err_exit;
 		}
+
 		memset_io(data_buf->base, 0, data_buf->size);
+		data_buf->iova = dma_map_resource(dev, data_buf->phys_base,
+					data_buf->size, DMA_BIDIRECTIONAL, 0);
+		if (dma_mapping_error(dev, data_buf->iova))
+			log_event_err("%s(): oci_mem: err mapping data_buf\n",
+								__func__);
+		log_event_dbg("%s: data_buf:%s virt:%pK, phys:%lx, iova:%lx\n",
+			__func__, dev_name(dev), data_buf->base,
+			(unsigned long)data_buf->phys_base, data_buf->iova);
 
 		desc_buf->phys_base = pipe_connect->desc_fifo_base_offset +
 				ctx->usb_bam_data->usb_bam_fifo_baseaddr;
@@ -380,6 +397,16 @@
 			goto err_exit;
 		}
 		memset_io(desc_buf->base, 0, desc_buf->size);
+		desc_buf->iova = dma_map_resource(dev, desc_buf->phys_base,
+					desc_buf->size,
+					DMA_BIDIRECTIONAL, 0);
+		if (dma_mapping_error(dev, desc_buf->iova))
+			log_event_err("%s(): oci_mem: err mapping desc_buf\n",
+								__func__);
+
+		log_event_dbg("%s: desc_buf:%s virt:%pK, phys:%lx, iova:%lx\n",
+			__func__, dev_name(dev), desc_buf->base,
+			(unsigned long)desc_buf->phys_base, desc_buf->iova);
 		break;
 	case SYSTEM_MEM:
 		log_event_dbg("%s: USB BAM using system memory\n", __func__);
@@ -391,56 +418,57 @@
 		}
 
 		/* BAM would use system memory, allocate FIFOs */
-		data_buf->size = pipe_connect->data_fifo_size;
+		data_fifo_size = data_buf->size = pipe_connect->data_fifo_size;
 		/* On platforms which use CI controller, USB HW can fetch
 		 * additional 128 bytes at the end of circular buffer when
 		 * AXI prefetch is enabled and hence requirement is to
 		 * allocate 512 bytes more than required length.
 		 */
 		if (pipe_connect->bam_type == CI_CTRL)
-			data_buf->base =
-				dma_alloc_coherent(&ctx->usb_bam_pdev->dev,
-				(pipe_connect->data_fifo_size +
-					DATA_FIFO_EXTRA_MEM_ALLOC_SIZE),
-				&(data_buf->phys_base),
-				GFP_KERNEL);
-		else
-			data_buf->base =
-				dma_alloc_coherent(&ctx->usb_bam_pdev->dev,
-				pipe_connect->data_fifo_size,
-				&(data_buf->phys_base),
-				GFP_KERNEL);
+			data_fifo_size += DATA_FIFO_EXTRA_MEM_ALLOC_SIZE;
+
+		data_buf->base = dma_alloc_attrs(dev, data_fifo_size,
+						&data_iova, GFP_KERNEL,
+						DMA_ATTR_FORCE_CONTIGUOUS);
 		if (!data_buf->base) {
-			log_event_err("%s: dma_alloc_coherent failed for data fifo\n",
+			log_event_err("%s: data_fifo: dma_alloc_attr failed\n",
 								__func__);
 			ret = -ENOMEM;
 			goto err_exit;
 		}
 		memset(data_buf->base, 0, pipe_connect->data_fifo_size);
 
+		data_buf->iova = data_iova;
+		dma_get_sgtable(dev, &data_sgt, data_buf->base, data_buf->iova,
+								data_fifo_size);
+		data_buf->phys_base = page_to_phys(sg_page(data_sgt.sgl));
+		sg_free_table(&data_sgt);
+		log_event_dbg("%s: data_buf:%s virt:%pK, phys:%lx, iova:%lx\n",
+			__func__, dev_name(dev), data_buf->base,
+			(unsigned long)data_buf->phys_base, data_buf->iova);
+
 		desc_buf->size = pipe_connect->desc_fifo_size;
-		desc_buf->base = dma_alloc_coherent(&ctx->usb_bam_pdev->dev,
-			pipe_connect->desc_fifo_size,
-			&(desc_buf->phys_base),
-			GFP_KERNEL);
+		desc_buf->base = dma_alloc_attrs(dev,
+				pipe_connect->desc_fifo_size,
+				&desc_iova, GFP_KERNEL,
+				DMA_ATTR_FORCE_CONTIGUOUS);
 		if (!desc_buf->base) {
-			log_event_err("%s: dma_alloc_coherent failed for desc fifo\n",
+			log_event_err("%s: desc_fifo: dma_alloc_attr failed\n",
 								__func__);
-			if (pipe_connect->bam_type == CI_CTRL)
-				dma_free_coherent(&ctx->usb_bam_pdev->dev,
-				(pipe_connect->data_fifo_size +
-					DATA_FIFO_EXTRA_MEM_ALLOC_SIZE),
-				data_buf->base,
-				data_buf->phys_base);
-			else
-				dma_free_coherent(&ctx->usb_bam_pdev->dev,
-				pipe_connect->data_fifo_size,
-				data_buf->base,
-				data_buf->phys_base);
+			dma_free_attrs(dev, data_fifo_size, data_buf->base,
+				data_buf->iova, DMA_ATTR_FORCE_CONTIGUOUS);
 			ret = -ENOMEM;
 			goto err_exit;
 		}
 		memset(desc_buf->base, 0, pipe_connect->desc_fifo_size);
+		desc_buf->iova = desc_iova;
+		dma_get_sgtable(dev, &desc_sgt, desc_buf->base, desc_buf->iova,
+								desc_buf->size);
+		desc_buf->phys_base = page_to_phys(sg_page(desc_sgt.sgl));
+		sg_free_table(&desc_sgt);
+		log_event_dbg("%s: desc_buf:%s virt:%pK, phys:%lx, iova:%lx\n",
+			__func__, dev_name(dev), desc_buf->base,
+			(unsigned long)desc_buf->phys_base, desc_buf->iova);
 		break;
 	default:
 		log_event_err("%s: invalid mem type\n", __func__);
@@ -476,35 +504,40 @@
 				&ctx->usb_bam_connections[idx];
 	struct sps_connect *sps_connection =
 				&ctx->usb_bam_sps.sps_connections[idx];
+	struct device *dev = &ctx->usb_bam_pdev->dev;
+	u32 data_fifo_size;
 
 	pr_debug("%s(): data size:%x desc size:%x\n",
 			__func__, sps_connection->data.size,
 			sps_connection->desc.size);
 
+	if (dev->parent)
+		dev = dev->parent;
+
 	switch (pipe_connect->mem_type) {
 	case SYSTEM_MEM:
 		log_event_dbg("%s: Freeing system memory used by PIPE\n",
 				__func__);
-		if (sps_connection->data.phys_base) {
+		if (sps_connection->data.iova) {
+			data_fifo_size = sps_connection->data.size;
 			if (cur_bam == CI_CTRL)
-				dma_free_coherent(&ctx->usb_bam_pdev->dev,
-					(sps_connection->data.size +
-						DATA_FIFO_EXTRA_MEM_ALLOC_SIZE),
+				data_fifo_size +=
+					DATA_FIFO_EXTRA_MEM_ALLOC_SIZE;
+
+			dma_free_attrs(dev, data_fifo_size,
 					sps_connection->data.base,
-					sps_connection->data.phys_base);
-			else
-				dma_free_coherent(&ctx->usb_bam_pdev->dev,
-					sps_connection->data.size,
-					sps_connection->data.base,
-					sps_connection->data.phys_base);
+					sps_connection->data.iova,
+					DMA_ATTR_FORCE_CONTIGUOUS);
+			sps_connection->data.iova = 0;
 			sps_connection->data.phys_base = 0;
 			pipe_connect->data_mem_buf.base = NULL;
 		}
-		if (sps_connection->desc.phys_base) {
-			dma_free_coherent(&ctx->usb_bam_pdev->dev,
-					sps_connection->desc.size,
+		if (sps_connection->desc.iova) {
+			dma_free_attrs(dev, sps_connection->desc.size,
 					sps_connection->desc.base,
-					sps_connection->desc.phys_base);
+					sps_connection->desc.iova,
+					DMA_ATTR_FORCE_CONTIGUOUS);
+			sps_connection->desc.iova = 0;
 			sps_connection->desc.phys_base = 0;
 			pipe_connect->desc_mem_buf.base = NULL;
 		}
@@ -512,11 +545,25 @@
 	case OCI_MEM:
 		log_event_dbg("Freeing oci memory used by BAM PIPE\n");
 		if (sps_connection->data.base) {
+			if (sps_connection->data.iova) {
+				dma_unmap_resource(dev,
+					sps_connection->data.iova,
+					sps_connection->data.size,
+					DMA_BIDIRECTIONAL, 0);
+				sps_connection->data.iova = 0;
+			}
 			iounmap(sps_connection->data.base);
 			sps_connection->data.base = NULL;
 			pipe_connect->data_mem_buf.base = NULL;
 		}
 		if (sps_connection->desc.base) {
+			if (sps_connection->desc.iova) {
+				dma_unmap_resource(dev,
+					sps_connection->desc.iova,
+					sps_connection->desc.size,
+					DMA_BIDIRECTIONAL, 0);
+				sps_connection->desc.iova = 0;
+			}
 			iounmap(sps_connection->desc.base);
 			sps_connection->desc.base = NULL;
 			pipe_connect->desc_mem_buf.base = NULL;
@@ -530,7 +577,8 @@
 	return 0;
 }
 
-static int connect_pipe(enum usb_ctrl cur_bam, u8 idx, u32 *usb_pipe_idx)
+static int connect_pipe(enum usb_ctrl cur_bam, u8 idx, u32 *usb_pipe_idx,
+							unsigned long iova)
 {
 	int ret;
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
@@ -575,9 +623,11 @@
 	if (dir == USB_TO_PEER_PERIPHERAL) {
 		sps_connection->mode = SPS_MODE_SRC;
 		*usb_pipe_idx = pipe_connect->src_pipe_index;
+		sps_connection->dest_iova = iova;
 	} else {
 		sps_connection->mode = SPS_MODE_DEST;
 		*usb_pipe_idx = pipe_connect->dst_pipe_index;
+		sps_connection->source_iova = iova;
 	}
 
 	sps_connection->data = *data_buf;
@@ -1059,7 +1109,34 @@
 	return 0;
 }
 
-int usb_bam_connect(enum usb_ctrl cur_bam, int idx, u32 *bam_pipe_idx)
+int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
+				phys_addr_t *p_addr, u32 *bam_size)
+{
+	int ret = 0;
+	struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
+	struct usb_bam_pipe_connect *pipe_connect =
+					&ctx->usb_bam_connections[idx];
+	unsigned long peer_bam_handle;
+
+	ret = sps_phy2h(pipe_connect->dst_phy_addr, &peer_bam_handle);
+	if (ret) {
+		log_event_err("%s: sps_phy2h failed (src BAM) %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = sps_get_bam_addr(peer_bam_handle, p_addr, bam_size);
+	if (ret) {
+		log_event_err("%s: sps_get_bam_addr failed%d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int usb_bam_connect(enum usb_ctrl cur_bam, int idx, u32 *bam_pipe_idx,
+						unsigned long iova)
 {
 	int ret;
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
@@ -1110,7 +1187,7 @@
 	/* Set the BAM mode (host/device) according to connected pipe */
 	info[cur_bam].cur_bam_mode = pipe_connect->bam_mode;
 
-	ret = connect_pipe(cur_bam, idx, bam_pipe_idx);
+	ret = connect_pipe(cur_bam, idx, bam_pipe_idx, iova);
 	if (ret) {
 		log_event_err("%s: pipe connection[%d] failure\n",
 				__func__, idx);
@@ -3024,6 +3101,7 @@
 	struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
 	enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
 	struct sps_bam_props props;
+	struct device *dev;
 
 	memset(&props, 0, sizeof(props));
 
@@ -3059,8 +3137,16 @@
 		pr_debug("Register and enable HSUSB BAM\n");
 		props.options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
 	}
-	ret = sps_register_bam_device(&props, &ctx->h_bam);
 
+	dev = &ctx->usb_bam_pdev->dev;
+	if (dev && dev->parent && !device_property_present(dev->parent,
+						"qcom,smmu-s1-bypass")) {
+		pr_info("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
+						__func__, dev_name(dev));
+		props.options |= SPS_BAM_SMMU_EN;
+	}
+
+	ret = sps_register_bam_device(&props, &ctx->h_bam);
 	if (ret < 0) {
 		log_event_err("%s: register bam error %d\n", __func__, ret);
 		return -EFAULT;
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index 84765b1..d288e83 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -27,6 +27,8 @@
 
 #define UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN	0
 
+static struct workqueue_struct *ice_workqueue;
+
 static void ufs_qcom_ice_dump_regs(struct ufs_qcom_host *qcom_host, int offset,
 					int len, char *prefix)
 {
@@ -224,6 +226,13 @@
 	}
 
 	qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
+	ice_workqueue = alloc_workqueue("ice-set-key",
+			WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+	if (!ice_workqueue) {
+		dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
+			__func__);
+		goto out;
+	}
 	INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
 
 out:
@@ -284,7 +293,7 @@
 				if (!qcom_host->work_pending) {
 					qcom_host->req_pending = cmd->request;
 
-					if (!schedule_work(
+					if (!queue_work(ice_workqueue,
 						&qcom_host->ice_cfg_work)) {
 						qcom_host->req_pending = NULL;
 
@@ -404,7 +413,7 @@
 				if (!qcom_host->work_pending) {
 
 					qcom_host->req_pending = cmd->request;
-					if (!schedule_work(
+					if (!queue_work(ice_workqueue,
 						&qcom_host->ice_cfg_work)) {
 						qcom_host->req_pending = NULL;
 
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a6bc1da..8060142 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -6146,7 +6146,7 @@
 
 out:
 	ufshcd_scsi_unblock_requests(hba);
-	pm_runtime_put_sync(hba->dev);
+	pm_runtime_put(hba->dev);
 	return;
 }
 
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index ea7374f..187c80d 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -557,6 +557,12 @@
 	len = fifo_write_body(einfo, data, len, &write_index);
 	if (unlikely(len < 0))
 		return len;
+
+	/* All data writes need to be flushed to memory before the write index
+	 * is updated. This protects against a race condition where the remote
+	 * reads stale data because the write index was written before the data.
+	 */
+	wmb();
 	einfo->tx_ch_desc->write_index = write_index;
 	send_irq(einfo);
 
@@ -599,6 +605,11 @@
 	if (unlikely(len3 < 0))
 		return len3;
 
+	/* All data writes need to be flushed to memory before the write index
+	 * is updated. This protects against a race condition where the remote
+	 * reads stale data because the write index was written before the data.
+	 */
+	wmb();
 	einfo->tx_ch_desc->write_index = write_index;
 	send_irq(einfo);
 
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
index 5dd49e8..8a835f5 100644
--- a/drivers/soc/qcom/llcc-slice.c
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -80,6 +80,7 @@
 	const struct llcc_slice_config *llcc_data_ptr;
 	struct llcc_slice_desc *desc;
 	struct platform_device *pdev;
+	u32 sz, count;
 
 	if (of_parse_phandle_with_args(dev->of_node, "cache-slices",
 				       "#cache-cells", n, &phargs)) {
@@ -100,14 +101,17 @@
 	}
 
 	llcc_data_ptr = drv->slice_data;
+	sz = drv->llcc_config_data_sz;
+	count = 0;
 
-	while (llcc_data_ptr) {
+	while (llcc_data_ptr && count < sz) {
 		if (llcc_data_ptr->usecase_id == phargs.args[0])
 			break;
 		llcc_data_ptr++;
+		count++;
 	}
 
-	if (llcc_data_ptr == NULL) {
+	if (llcc_data_ptr == NULL || count == sz) {
 		pr_err("can't find %d usecase id\n", phargs.args[0]);
 		return ERR_PTR(-ENODEV);
 	}
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 720ac31..c1103c7 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1523,6 +1523,11 @@
 	}
 	buffer = dmabuf->priv;
 
+	if (!is_buffer_hlos_assigned(buffer)) {
+		pr_err("%s: cannot sync a secure dmabuf\n", __func__);
+		dma_buf_put(dmabuf);
+		return -EINVAL;
+	}
 	dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
 			       buffer->sg_table->nents, DMA_BIDIRECTIONAL);
 	dma_buf_put(dmabuf);
diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c
index 2a8791a..9d53391 100644
--- a/drivers/staging/android/ion/msm/msm_ion.c
+++ b/drivers/staging/android/ion/msm/msm_ion.c
@@ -344,7 +344,7 @@
 	if (!ION_IS_CACHED(flags))
 		return 0;
 
-	if (flags & ION_FLAG_SECURE)
+	if (!is_buffer_hlos_assigned(ion_handle_buffer(handle)))
 		return 0;
 
 	table = ion_sg_table(client, handle);
@@ -679,6 +679,20 @@
 	return -EINVAL;
 }
 
+bool is_buffer_hlos_assigned(struct ion_buffer *buffer)
+{
+	bool is_hlos = false;
+
+	if (buffer->heap->type == (enum ion_heap_type)ION_HEAP_TYPE_HYP_CMA &&
+	    (buffer->flags & ION_FLAG_CP_HLOS))
+		is_hlos = true;
+
+	if (get_secure_vmid(buffer->flags) <= 0)
+		is_hlos = true;
+
+	return is_hlos;
+}
+
 int get_vmid(unsigned long flags)
 {
 	int vmid;
@@ -755,9 +769,9 @@
 
 		down_read(&mm->mmap_sem);
 
-		start = (unsigned long)data.flush_data.vaddr;
-		end = (unsigned long)data.flush_data.vaddr
-			+ data.flush_data.length;
+		start = (unsigned long)data.flush_data.vaddr +
+			data.flush_data.offset;
+		end = start + data.flush_data.length;
 
 		if (check_vaddr_bounds(start, end)) {
 			pr_err("%s: virtual address %pK is out of bounds\n",
diff --git a/drivers/staging/android/ion/msm/msm_ion.h b/drivers/staging/android/ion/msm/msm_ion.h
index 741d017..ad7b1c5 100644
--- a/drivers/staging/android/ion/msm/msm_ion.h
+++ b/drivers/staging/android/ion/msm/msm_ion.h
@@ -174,6 +174,8 @@
 		void *vaddr, unsigned int offset, unsigned long len,
 		unsigned int cmd);
 
+bool is_buffer_hlos_assigned(struct ion_buffer *buffer);
+
 #else
 static inline struct ion_client *msm_ion_client_create(const char *name)
 {
@@ -202,6 +204,10 @@
 	return -ENODEV;
 }
 
+static bool is_buffer_hlos_assigned(struct ion_buffer *buffer)
+{
+	return true;
+}
 #endif /* CONFIG_ION */
 
 #endif
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 8d67f76..4747949 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -221,6 +221,22 @@
 	return 0;
 }
 
+static int test_task_state(struct task_struct *p, int state)
+{
+	struct task_struct *t;
+
+	for_each_thread(p, t) {
+		task_lock(t);
+		if (t->state & state) {
+			task_unlock(t);
+			return 1;
+		}
+		task_unlock(t);
+	}
+
+	return 0;
+}
+
 static int test_task_lmk_waiting(struct task_struct *p)
 {
 	struct task_struct *t;
@@ -435,7 +451,7 @@
 	int other_free;
 	int other_file;
 
-	if (mutex_lock_interruptible(&scan_mutex) < 0)
+	if (!mutex_trylock(&scan_mutex))
 		return 0;
 
 	other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
@@ -495,8 +511,6 @@
 		if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
 			if (test_task_lmk_waiting(tsk)) {
 				rcu_read_unlock();
-				/* give the system time to free up the memory */
-				msleep_interruptible(20);
 				mutex_unlock(&scan_mutex);
 				return 0;
 			}
@@ -533,6 +547,16 @@
 		long cache_limit = minfree * (long)(PAGE_SIZE / 1024);
 		long free = other_free * (long)(PAGE_SIZE / 1024);
 
+		if (test_task_lmk_waiting(selected) &&
+		    (test_task_state(selected, TASK_UNINTERRUPTIBLE))) {
+			lowmem_print(2, "'%s' (%d) is already killed\n",
+				     selected->comm,
+				     selected->pid);
+			rcu_read_unlock();
+			mutex_unlock(&scan_mutex);
+			return 0;
+		}
+
 		task_lock(selected);
 		send_sig(SIGKILL, selected, 0);
 		if (selected->mm)
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index acbd26b..27bf54b 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -58,4 +58,4 @@
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
 obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
 obj-$(CONFIG_THERMAL_QPNP_ADC_TM)	+= qpnp-adc-tm.o
-obj-$(CONFIG_THERMAL_TSENS)	+= msm-tsens.o tsens2xxx.o tsens-dbg.o
+obj-$(CONFIG_THERMAL_TSENS)	+= msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o
diff --git a/drivers/thermal/tsens-dbg.c b/drivers/thermal/tsens-dbg.c
index 2e795b1..e1fc6b9 100644
--- a/drivers/thermal/tsens-dbg.c
+++ b/drivers/thermal/tsens-dbg.c
@@ -12,7 +12,9 @@
  */
 
 #include <asm/arch_timer.h>
+#include <linux/platform_device.h>
 #include "tsens.h"
+#include "tsens-mtc.h"
 
 /* debug defines */
 #define	TSENS_DBG_BUS_ID_0			0
@@ -42,6 +44,177 @@
 	int (*dbg_func)(struct tsens_device *, u32, u32, int *);
 };
 
+static ssize_t
+zonemask_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct tsens_device *tmdev = NULL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	return snprintf(buf, PAGE_SIZE,
+		"Zone =%d th1=%d th2=%d\n", tmdev->mtcsys.zone_mtc,
+				tmdev->mtcsys.th1, tmdev->mtcsys.th2);
+}
+
+static ssize_t
+zonemask_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int ret;
+	struct tsens_device *tmdev = NULL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	ret = sscanf(buf, "%d %d %d", &tmdev->mtcsys.zone_mtc,
+				&tmdev->mtcsys.th1, &tmdev->mtcsys.th2);
+
+	if (ret != TSENS_ZONEMASK_PARAMS) {
+		pr_err("Invalid command line arguments\n");
+		count = -EINVAL;
+	} else {
+		pr_debug("store zone_mtc=%d th1=%d th2=%d\n",
+				tmdev->mtcsys.zone_mtc,
+				tmdev->mtcsys.th1, tmdev->mtcsys.th2);
+		ret = tsens_set_mtc_zone_sw_mask(tmdev->mtcsys.zone_mtc,
+					tmdev->mtcsys.th1, tmdev->mtcsys.th2);
+		if (ret < 0) {
+			pr_err("Invalid command line arguments\n");
+			count = -EINVAL;
+		}
+	}
+
+	return count;
+}
+
+static ssize_t
+zonelog_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int ret, zlog[TSENS_MTC_ZONE_LOG_SIZE];
+	struct tsens_device *tmdev = NULL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	ret = tsens_get_mtc_zone_log(tmdev->mtcsys.zone_log, zlog);
+	if (ret < 0) {
+		pr_err("Invalid command line arguments\n");
+		return -EINVAL;
+	}
+
+	return snprintf(buf, PAGE_SIZE,
+		"Log[0]=%d\nLog[1]=%d\nLog[2]=%d\nLog[3]=%d\nLog[4]=%d\nLog[5]=%d\n",
+			zlog[0], zlog[1], zlog[2], zlog[3], zlog[4], zlog[5]);
+}
+
+static ssize_t
+zonelog_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int ret;
+	struct tsens_device *tmdev = NULL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	ret = kstrtou32(buf, 0, &tmdev->mtcsys.zone_log);
+	if (ret < 0) {
+		pr_err("Invalid command line arguments\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t
+zonehist_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int ret, zhist[TSENS_MTC_ZONE_HISTORY_SIZE];
+	struct tsens_device *tmdev = NULL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	ret = tsens_get_mtc_zone_history(tmdev->mtcsys.zone_hist, zhist);
+	if (ret < 0) {
+		pr_err("Invalid command line arguments\n");
+		return -EINVAL;
+	}
+
+	return snprintf(buf, PAGE_SIZE,
+		"Cool = %d\nYellow = %d\nRed = %d\n",
+			zhist[0], zhist[1], zhist[2]);
+}
+
+static ssize_t
+zonehist_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int ret;
+	struct tsens_device *tmdev = NULL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	ret = kstrtou32(buf, 0, &tmdev->mtcsys.zone_hist);
+	if (ret < 0) {
+		pr_err("Invalid command line arguments\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static struct device_attribute tsens_mtc_dev_attr[] = {
+	__ATTR(zonemask, 0644, zonemask_show, zonemask_store),
+	__ATTR(zonelog, 0644, zonelog_show, zonelog_store),
+	__ATTR(zonehist, 0644, zonehist_show, zonehist_store),
+};
+
+static int tsens_dbg_mtc_data(struct tsens_device *data,
+					u32 id, u32 dbg_type, int *val)
+{
+	int result = 0, i;
+	struct tsens_device *tmdev = NULL;
+	struct device_attribute *attr_ptr = NULL;
+
+	attr_ptr = tsens_mtc_dev_attr;
+	tmdev = data;
+
+	for (i = 0; i < ARRAY_SIZE(tsens_mtc_dev_attr); i++) {
+		result = device_create_file(&tmdev->pdev->dev, &attr_ptr[i]);
+		if (result < 0)
+			goto error;
+	}
+
+	return result;
+
+error:
+	for (i--; i >= 0; i--)
+		device_remove_file(&tmdev->pdev->dev, &attr_ptr[i]);
+
+	return result;
+}
+
 static int tsens_dbg_log_temp_reads(struct tsens_device *data, u32 id,
 					u32 dbg_type, int *temp)
 {
@@ -206,6 +379,7 @@
 	[TSENS_DBG_LOG_INTERRUPT_TIMESTAMP] = {
 			tsens_dbg_log_interrupt_timestamp},
 	[TSENS_DBG_LOG_BUS_ID_DATA] = {tsens_dbg_log_bus_id_data},
+	[TSENS_DBG_MTC_DATA] = {tsens_dbg_mtc_data},
 };
 
 int tsens2xxx_dbg(struct tsens_device *data, u32 id, u32 dbg_type, int *val)
diff --git a/drivers/thermal/tsens-mtc.c b/drivers/thermal/tsens-mtc.c
new file mode 100644
index 0000000..529503f
--- /dev/null
+++ b/drivers/thermal/tsens-mtc.c
@@ -0,0 +1,195 @@
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "tsens.h"
+#include "tsens-mtc.h"
+
+struct tsens_device *tsens_controller_is_present(void)
+{
+	struct tsens_device *tmdev_chip = NULL;
+
+	if (list_empty(&tsens_device_list)) {
+		pr_err("%s: TSENS controller not available\n", __func__);
+		return tmdev_chip;
+	}
+
+	list_for_each_entry(tmdev_chip, &tsens_device_list, list)
+		return tmdev_chip;
+
+	return tmdev_chip;
+}
+EXPORT_SYMBOL(tsens_controller_is_present);
+
+static int tsens_mtc_reset_history_counter(unsigned int zone)
+{
+	unsigned int reg_cntl, is_valid;
+	void __iomem *sensor_addr;
+	struct tsens_device *tmdev = NULL;
+
+	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
+		return -EINVAL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(tmdev->tsens_tm_addr);
+	reg_cntl = readl_relaxed((sensor_addr +
+		(zone * TSENS_SN_ADDR_OFFSET)));
+	is_valid = (reg_cntl & TSENS_RESET_HISTORY_MASK)
+				>> TSENS_RESET_HISTORY_SHIFT;
+	if (!is_valid) {
+		/*Enable the bit to reset counter*/
+		writel_relaxed(reg_cntl | (1 << TSENS_RESET_HISTORY_SHIFT),
+				(sensor_addr + (zone * TSENS_SN_ADDR_OFFSET)));
+		reg_cntl = readl_relaxed((sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+		pr_debug("tsens : zone =%d reg=%x\n", zone, reg_cntl);
+	}
+
+	/*Disble the bit to start counter*/
+	writel_relaxed(reg_cntl & ~(1 << TSENS_RESET_HISTORY_SHIFT),
+				(sensor_addr + (zone * TSENS_SN_ADDR_OFFSET)));
+	reg_cntl = readl_relaxed((sensor_addr +
+			(zone * TSENS_SN_ADDR_OFFSET)));
+	pr_debug("tsens : zone =%d reg=%x\n", zone, reg_cntl);
+
+	return 0;
+}
+EXPORT_SYMBOL(tsens_mtc_reset_history_counter);
+
+int tsens_set_mtc_zone_sw_mask(unsigned int zone, unsigned int th1_enable,
+				unsigned int th2_enable)
+{
+	unsigned int reg_cntl;
+	void __iomem *sensor_addr;
+	struct tsens_device *tmdev = NULL;
+
+	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
+		return -EINVAL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
+					(tmdev->tsens_tm_addr);
+
+	if (th1_enable && th2_enable)
+		writel_relaxed(TSENS_MTC_IN_EFFECT,
+				(sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+	if (!th1_enable && !th2_enable)
+		writel_relaxed(TSENS_MTC_DISABLE,
+				(sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+	if (th1_enable && !th2_enable)
+		writel_relaxed(TSENS_TH1_MTC_IN_EFFECT,
+				(sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+	if (!th1_enable && th2_enable)
+		writel_relaxed(TSENS_TH2_MTC_IN_EFFECT,
+				(sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+	reg_cntl = readl_relaxed((sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+	pr_debug("tsens : zone =%d th1=%d th2=%d reg=%x\n",
+		zone, th1_enable, th2_enable, reg_cntl);
+
+	return 0;
+}
+EXPORT_SYMBOL(tsens_set_mtc_zone_sw_mask);
+
+int tsens_get_mtc_zone_log(unsigned int zone, void *zone_log)
+{
+	unsigned int i, reg_cntl, is_valid, log[TSENS_MTC_ZONE_LOG_SIZE];
+	int *zlog = (int *)zone_log;
+	void __iomem *sensor_addr;
+	struct tsens_device *tmdev = NULL;
+
+	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
+		return -EINVAL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_tm_addr);
+
+	reg_cntl = readl_relaxed((sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+	is_valid = (reg_cntl & TSENS_LOGS_VALID_MASK)
+				>> TSENS_LOGS_VALID_SHIFT;
+	if (is_valid) {
+		log[0] = (reg_cntl & TSENS_LOGS_LATEST_MASK);
+		log[1] = (reg_cntl & TSENS_LOGS_LOG1_MASK)
+				>> TSENS_LOGS_LOG1_SHIFT;
+		log[2] = (reg_cntl & TSENS_LOGS_LOG2_MASK)
+				>> TSENS_LOGS_LOG2_SHIFT;
+		log[3] = (reg_cntl & TSENS_LOGS_LOG3_MASK)
+				>> TSENS_LOGS_LOG3_SHIFT;
+		log[4] = (reg_cntl & TSENS_LOGS_LOG4_MASK)
+				>> TSENS_LOGS_LOG4_SHIFT;
+		log[5] = (reg_cntl & TSENS_LOGS_LOG5_MASK)
+				>> TSENS_LOGS_LOG5_SHIFT;
+		for (i = 0; i < (TSENS_MTC_ZONE_LOG_SIZE); i++) {
+			*(zlog+i) = log[i];
+			pr_debug("Log[%d]=%d\n", i, log[i]);
+		}
+	} else {
+		pr_debug("tsens: Valid bit disabled\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(tsens_get_mtc_zone_log);
+
+int tsens_get_mtc_zone_history(unsigned int zone, void *zone_hist)
+{
+	unsigned int i, reg_cntl, hist[TSENS_MTC_ZONE_HISTORY_SIZE];
+	int *zhist = (int *)zone_hist;
+	void __iomem *sensor_addr;
+	struct tsens_device *tmdev = NULL;
+
+	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
+		return -EINVAL;
+
+	tmdev = tsens_controller_is_present();
+	if (!tmdev) {
+		pr_err("No TSENS controller present\n");
+		return -EPROBE_DEFER;
+	}
+
+	sensor_addr = TSENS_TM_MTC_ZONE0_HISTORY(tmdev->tsens_tm_addr);
+	reg_cntl = readl_relaxed((sensor_addr +
+				(zone * TSENS_SN_ADDR_OFFSET)));
+
+	hist[0] = (reg_cntl & TSENS_PS_COOL_CMD_MASK);
+	hist[1] = (reg_cntl & TSENS_PS_YELLOW_CMD_MASK)
+			>> TSENS_PS_YELLOW_CMD_SHIFT;
+	hist[2] = (reg_cntl & TSENS_PS_RED_CMD_MASK)
+			>> TSENS_PS_RED_CMD_SHIFT;
+	for (i = 0; i < (TSENS_MTC_ZONE_HISTORY_SIZE); i++) {
+		*(zhist+i) = hist[i];
+		pr_debug("tsens : %d\n", hist[i]);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(tsens_get_mtc_zone_history);
diff --git a/drivers/thermal/tsens-mtc.h b/drivers/thermal/tsens-mtc.h
new file mode 100644
index 0000000..979513f
--- /dev/null
+++ b/drivers/thermal/tsens-mtc.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define TSENS_NUM_MTC_ZONES_SUPPORT 3
+#define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(n)      ((n) + 0x140)
+#define TSENS_TM_MTC_ZONE0_LOG(n)               ((n) + 0x150)
+#define TSENS_TM_MTC_ZONE0_HISTORY(n)           ((n) + 0x160)
+#define TSENS_SN_ADDR_OFFSET             0x4
+#define TSENS_RESET_HISTORY_MASK        0x4
+#define TSENS_ZONEMASK_PARAMS           3
+#define TSENS_MTC_ZONE_LOG_SIZE         6
+#define TSENS_MTC_ZONE_HISTORY_SIZE     3
+
+#define TSENS_TH1_MTC_IN_EFFECT               BIT(0)
+#define TSENS_TH2_MTC_IN_EFFECT               BIT(1)
+#define TSENS_MTC_IN_EFFECT                     0x3
+#define TSENS_MTC_DISABLE                       0x0
+
+#define TSENS_LOGS_VALID_MASK      0x40000000
+#define TSENS_LOGS_VALID_SHIFT     30
+#define TSENS_LOGS_LATEST_MASK    0x0000001f
+#define TSENS_LOGS_LOG1_MASK      0x000003e0
+#define TSENS_LOGS_LOG2_MASK      0x00007c00
+#define TSENS_LOGS_LOG3_MASK      0x000f8000
+#define TSENS_LOGS_LOG4_MASK      0x01f00000
+#define TSENS_LOGS_LOG5_MASK      0x3e000000
+#define TSENS_LOGS_LOG1_SHIFT     5
+#define TSENS_LOGS_LOG2_SHIFT     10
+#define TSENS_LOGS_LOG3_SHIFT     15
+#define TSENS_LOGS_LOG4_SHIFT     20
+#define TSENS_LOGS_LOG5_SHIFT     25
+
+#define TSENS_PS_RED_CMD_MASK   0x3ff00000
+#define TSENS_PS_YELLOW_CMD_MASK        0x000ffc00
+#define TSENS_PS_COOL_CMD_MASK  0x000003ff
+#define TSENS_PS_YELLOW_CMD_SHIFT       0xa
+#define TSENS_PS_RED_CMD_SHIFT  0x14
+
+#define TSENS_RESET_HISTORY_SHIFT       2
+
+#define TSENS_ZONEMASK_PARAMS           3
+#define TSENS_MTC_ZONE_LOG_SIZE         6
+#define TSENS_MTC_ZONE_HISTORY_SIZE     3
+
+extern int tsens_get_mtc_zone_history(unsigned int zone, void *zone_hist);
+extern struct tsens_device *tsens_controller_is_present(void);
+extern int tsens_set_mtc_zone_sw_mask(unsigned int zone,
+			unsigned int th1_enable, unsigned int th2_enable);
+extern int tsens_get_mtc_zone_log(unsigned int zone, void *zone_log);
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index ec2d592..ae4741d 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -32,6 +32,7 @@
 	TSENS_DBG_LOG_TEMP_READS,
 	TSENS_DBG_LOG_INTERRUPT_TIMESTAMP,
 	TSENS_DBG_LOG_BUS_ID_DATA,
+	TSENS_DBG_MTC_DATA,
 	TSENS_DBG_LOG_MAX
 };
 
@@ -114,6 +115,15 @@
 	u32				cycle_compltn_monitor_mask;
 	bool				wd_bark;
 	u32				wd_bark_mask;
+	bool				mtc;
+};
+
+struct tsens_mtc_sysfs {
+	uint32_t	zone_log;
+	int			zone_mtc;
+	int			th1;
+	int			th2;
+	uint32_t	zone_hist;
 };
 
 struct tsens_device {
@@ -130,8 +140,10 @@
 	spinlock_t			tsens_upp_low_lock;
 	const struct tsens_data		*ctrl_data;
 	struct tsens_sensor		sensor[0];
+	struct tsens_mtc_sysfs	mtcsys;
 };
 
 extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx;
+extern struct list_head tsens_device_list;
 
 #endif /* __QCOM_TSENS_H__ */
diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c
index fd625ae..50c847f 100644
--- a/drivers/thermal/tsens2xxx.c
+++ b/drivers/thermal/tsens2xxx.c
@@ -570,6 +570,11 @@
 	spin_lock_init(&tmdev->tsens_crit_lock);
 	spin_lock_init(&tmdev->tsens_upp_low_lock);
 
+	if (tmdev->ctrl_data->mtc) {
+		if (tmdev->ops->dbg)
+			tmdev->ops->dbg(tmdev, 0, TSENS_DBG_MTC_DATA, NULL);
+	}
+
 	return 0;
 }
 
@@ -628,6 +633,7 @@
 	.wd_bark			= false,
 	.wd_bark_mask			= 1,
 	.ops				= &ops_tsens2xxx,
+	.mtc				= true,
 };
 
 const struct tsens_data data_tsens23xx = {
@@ -636,6 +642,7 @@
 	.wd_bark			= true,
 	.wd_bark_mask			= 1,
 	.ops				= &ops_tsens2xxx,
+	.mtc				= false,
 };
 
 const struct tsens_data data_tsens24xx = {
@@ -645,4 +652,5 @@
 	/* Enable Watchdog monitoring by unmasking */
 	.wd_bark_mask			= 0,
 	.ops				= &ops_tsens2xxx,
+	.mtc				= false,
 };
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 67a71ba..0ce23c3 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1286,6 +1286,8 @@
 
 	geni_se_rx_dma_unprep(msm_port->wrapper_dev, msm_port->rx_dma,
 			      DMA_RX_BUF_SIZE);
+	msm_port->rx_dma = (dma_addr_t)NULL;
+
 	rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN);
 	if (unlikely(!msm_port->rx_buf)) {
 		IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: NULL Rx_buf\n",
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 64ed834..719fcbf 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1173,6 +1173,9 @@
 	device_property_read_u32(dev, "snps,xhci-imod-value",
 			&dwc->xhci_imod_value);
 
+	dwc->core_id = -1;
+	device_property_read_u32(dev, "usb-core-id", &dwc->core_id);
+
 	dwc->usb3_lpm_capable = device_property_read_bool(dev,
 				"snps,usb3_lpm_capable");
 
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 68a40f9..a8400dd 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -954,6 +954,7 @@
  *			increments or 0 to disable.
  * @create_reg_debugfs: create debugfs entry to allow dwc3 register dump
  * @xhci_imod_value: imod value to use with xhci
+ * @core_id: usb core id to differentiate different controller
  */
 struct dwc3 {
 	struct usb_ctrlrequest	*ctrl_req;
@@ -1150,6 +1151,7 @@
 	struct dwc3_gadget_events	dbg_gadget_events;
 	bool			create_reg_debugfs;
 	u32			xhci_imod_value;
+	int			core_id;
 };
 
 /* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dbm.c b/drivers/usb/dwc3/dbm.c
index 3860a1a..44c082a 100644
--- a/drivers/usb/dwc3/dbm.c
+++ b/drivers/usb/dwc3/dbm.c
@@ -450,7 +450,7 @@
 }
 
 
-int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, phys_addr_t addr,
+int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, unsigned long addr,
 				u32 size, u8 dst_pipe_idx)
 {
 	u8 dbm_ep = dst_pipe_idx;
diff --git a/drivers/usb/dwc3/dbm.h b/drivers/usb/dwc3/dbm.h
index 260afc2..d8e1ce9 100644
--- a/drivers/usb/dwc3/dbm.h
+++ b/drivers/usb/dwc3/dbm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2017 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
@@ -63,7 +63,7 @@
 int dbm_get_num_of_eps_configured(struct dbm *dbm);
 int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo, u32 addr_hi,
 				int size);
-int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, phys_addr_t addr,
+int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, unsigned long addr,
 				u32 size, u8 dst_pipe_idx);
 void dbm_set_speed(struct dbm *dbm, bool speed);
 void dbm_enable(struct dbm *dbm);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 3b92db9..5c70da8 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -461,7 +461,7 @@
  * @size - size of data fifo.
  *
  */
-int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
+int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr,
 			 u32 size, u8 dst_pipe_idx)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
@@ -3020,6 +3020,13 @@
 		return ret;
 	}
 	dev_dbg(mdwc->dev, "IOMMU mapping created: %pK\n", mdwc->iommu_map);
+	ret = iommu_domain_set_attr(mdwc->iommu_map->domain,
+			DOMAIN_ATTR_UPSTREAM_IOVA_ALLOCATOR, &atomic_ctx);
+	if (ret) {
+		dev_err(mdwc->dev, "set UPSTREAM_IOVA_ALLOCATOR failed(%d)\n",
+				ret);
+		goto release_mapping;
+	}
 
 	ret = iommu_domain_set_attr(mdwc->iommu_map->domain, DOMAIN_ATTR_ATOMIC,
 			&atomic_ctx);
@@ -3141,14 +3148,6 @@
 	if (!mdwc)
 		return -ENOMEM;
 
-	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
-		dev_err(&pdev->dev, "setting DMA mask to 64 failed.\n");
-		if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
-			dev_err(&pdev->dev, "setting DMA mask to 32 failed.\n");
-			return -EOPNOTSUPP;
-		}
-	}
-
 	platform_set_drvdata(pdev, mdwc);
 	mdwc->dev = &pdev->dev;
 
@@ -3341,6 +3340,15 @@
 	if (ret)
 		goto err;
 
+	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
+		dev_err(&pdev->dev, "setting DMA mask to 64 failed.\n");
+		if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
+			dev_err(&pdev->dev, "setting DMA mask to 32 failed.\n");
+			ret = -EOPNOTSUPP;
+			goto uninit_iommu;
+		}
+	}
+
 	/* Assumes dwc3 is the first DT child of dwc3-msm */
 	dwc3_node = of_get_next_available_child(node, NULL);
 	if (!dwc3_node) {
@@ -3944,6 +3952,7 @@
 	if (ret)
 		goto err;
 
+	dbg_event(0xFF, "USB_lpm_state", atomic_read(&dwc->in_lpm));
 	/*
 	 * stop host mode functionality performs autosuspend with mdwc
 	 * device, and it may take sometime to call PM runtime suspend.
@@ -3951,6 +3960,12 @@
 	 * suspend immediately to put USB controller and PHYs into suspend.
 	 */
 	ret = pm_runtime_suspend(mdwc->dev);
+	/*
+	 * If mdwc device is already suspended, pm_runtime_suspend() API
+	 * returns 1, which is not error. Overwrite with zero if it is.
+	 */
+	if (ret > 0)
+		ret = 0;
 	dbg_event(0xFF, "pm_runtime_sus", ret);
 
 	dwc->maximum_speed = usb_speed;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 51504b0..70c00d2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1306,7 +1306,7 @@
 
 	if (req->request.status == -EINPROGRESS) {
 		ret = -EBUSY;
-		dev_err(dwc->dev, "%s: %p request already in queue",
+		dev_err_ratelimited(dwc->dev, "%s: %p request already in queue",
 					dep->name, req);
 		return ret;
 	}
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 3f79aa4..8b159c3 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -52,7 +52,7 @@
 	return irq;
 }
 
-#define NUMBER_OF_PROPS	4
+#define NUMBER_OF_PROPS	5
 int dwc3_host_init(struct dwc3 *dwc)
 {
 	struct property_entry	props[NUMBER_OF_PROPS];
@@ -62,6 +62,7 @@
 	struct platform_device	*dwc3_pdev = to_platform_device(dwc->dev);
 	int			prop_idx = 0;
 	struct property_entry	imod_prop;
+	struct property_entry	core_id_prop;
 
 	irq = dwc3_host_get_irq(dwc);
 	if (irq < 0)
@@ -112,6 +113,15 @@
 		props[prop_idx++] = imod_prop;
 	}
 
+	if (dwc->core_id >= 0) {
+		core_id_prop.name  = "usb-core-id";
+		core_id_prop.length  = sizeof(u32);
+		core_id_prop.is_string = false;
+		core_id_prop.is_array = false;
+		core_id_prop.value.u32_data = dwc->core_id;
+		props[prop_idx++] = core_id_prop;
+	}
+
 	/**
 	 * WORKAROUND: dwc3 revisions <=3.00a have a limitation
 	 * where Port Disable command doesn't work.
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 71e84fd..b1a4a29 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -2507,6 +2507,10 @@
 	struct f_gsi *gsi = func_to_gsi(f);
 	struct rndis_params *params;
 	int status;
+	__u8  class;
+	__u8  subclass;
+	__u8  proto;
+
 
 	if (gsi->prot_id == IPA_USB_RMNET ||
 		gsi->prot_id == IPA_USB_DIAG)
@@ -2588,6 +2592,85 @@
 					DEFAULT_PKT_ALIGNMENT_FACTOR);
 		rndis_set_pkt_alignment_factor(gsi->params,
 					DEFAULT_PKT_ALIGNMENT_FACTOR);
+
+		/* Windows7/Windows10 automatically loads RNDIS drivers for
+		 * class drivers which represents MISC_ACTIVE_SYNC,
+		 * MISC_RNDIS_OVER_ETHERNET & WIRELESS_CONTROLLER_REMOTE_NDIS.
+		 * All the codes listed below are from
+		 * http://www.usb.org/developers/defined_class and its unknown
+		 * why windows loads rndis class driver for some of them.
+		 * Note that, Windows loads NDIS6 stack automatically for
+		 * MISC_RNDIS_OVER_ETHERNET. Windows loads NDIS5 stack for
+		 * MISC_ACTIVE_SYNC and WIRELESS_CONTROLLER_REMOTE_NDIS.
+		 * For other class codes, NDIS stack can be selected using
+		 * customized INF file but that defeats the purpose as its
+		 * expected to load drivers automatically for known class
+		 * drivers published by usbif.
+		 * Linux rndis host driver supports MISC_ACTIVE_SYNC and
+		 * WIRELESS_CONTROLLER_REMOTE_NDIS as of now.
+		 * Default to rndis over ethernet which loads NDIS6 drivers
+		 * for windows7/windows10 to avoid data stall issues
+		 */
+		if (gsi->rndis_id == RNDIS_ID_UNKNOWN)
+			gsi->rndis_id = MISC_RNDIS_OVER_ETHERNET;
+
+		switch (gsi->rndis_id) {
+		default:
+			/* fall throug */
+		case WIRELESS_CONTROLLER_REMOTE_NDIS:
+			class = USB_CLASS_WIRELESS_CONTROLLER;
+			subclass = 0x01;
+			proto = 0x03;
+			break;
+		case MISC_ACTIVE_SYNC:
+			class = USB_CLASS_MISC;
+			subclass = 0x01;
+			proto = 0x01;
+			break;
+		case MISC_RNDIS_OVER_ETHERNET:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x01;
+			break;
+		case MISC_RNDIS_OVER_WIFI:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x02;
+			break;
+		case MISC_RNDIS_OVER_WIMAX:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x03;
+			break;
+		case MISC_RNDIS_OVER_WWAN:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x04;
+			break;
+		case MISC_RNDIS_FOR_IPV4:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x05;
+			break;
+		case MISC_RNDIS_FOR_IPV6:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x06;
+			break;
+		case MISC_RNDIS_FOR_GPRS:
+			class = USB_CLASS_MISC;
+			subclass = 0x04;
+			proto = 0x07;
+			break;
+		}
+
+		info.iad_desc->bFunctionClass = class;
+		info.iad_desc->bFunctionSubClass = subclass;
+		info.iad_desc->bFunctionProtocol = proto;
+		info.ctrl_desc->bInterfaceClass = class;
+		info.ctrl_desc->bInterfaceSubClass = subclass;
+		info.ctrl_desc->bInterfaceProtocol = proto;
+
 		break;
 	case IPA_USB_MBIM:
 		info.string_defs = mbim_gsi_string_defs;
@@ -3086,6 +3169,43 @@
 	.ct_owner	= THIS_MODULE,
 };
 
+static ssize_t gsi_rndis_class_id_show(struct config_item *item, char *page)
+{
+	struct f_gsi *gsi = to_gsi_opts(item)->gsi;
+
+	return snprintf(page, PAGE_SIZE, "%d\n", gsi->rndis_id);
+}
+
+static ssize_t gsi_rndis_class_id_store(struct config_item *item,
+			const char *page, size_t len)
+{
+	struct f_gsi *gsi = to_gsi_opts(item)->gsi;
+	u8 id;
+
+	if (kstrtou8(page, 0, &id))
+		return -EINVAL;
+
+	if (id > RNDIS_ID_UNKNOWN && id < RNDIS_ID_MAX)
+		gsi->rndis_id = id;
+	else
+		return -EINVAL;
+
+	return len;
+}
+CONFIGFS_ATTR(gsi_, rndis_class_id);
+
+static struct configfs_attribute *gsi_rndis_attrs[] = {
+	&gsi_attr_info,
+	&gsi_attr_rndis_class_id,
+	NULL,
+};
+
+static struct config_item_type gsi_func_rndis_type = {
+	.ct_item_ops	= &gsi_item_ops,
+	.ct_attrs	= gsi_rndis_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
 static void gsi_inst_clean(struct gsi_opts *opts)
 {
 	if (opts->gsi->c_port.ctrl_device.fops)
@@ -3127,6 +3247,10 @@
 	}
 	mutex_unlock(&inst_status[prot_id].gsi_lock);
 
+	if (prot_id == IPA_USB_RNDIS)
+		config_group_init_type_name(&opts->func_inst.group, "",
+					    &gsi_func_rndis_type);
+
 	gsi = gsi_function_init(prot_id);
 	if (IS_ERR(gsi))
 		return PTR_ERR(gsi);
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index 295f681..fa36d05 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -122,6 +122,20 @@
 	GSI_CTRL_NOTIFY_RESPONSE_AVAILABLE,
 };
 
+enum rndis_class_id {
+	RNDIS_ID_UNKNOWN,
+	WIRELESS_CONTROLLER_REMOTE_NDIS,
+	MISC_ACTIVE_SYNC,
+	MISC_RNDIS_OVER_ETHERNET,
+	MISC_RNDIS_OVER_WIFI,
+	MISC_RNDIS_OVER_WIMAX,
+	MISC_RNDIS_OVER_WWAN,
+	MISC_RNDIS_FOR_IPV4,
+	MISC_RNDIS_FOR_IPV6,
+	MISC_RNDIS_FOR_GPRS,
+	RNDIS_ID_MAX,
+};
+
 #define MAXQUEUELEN 128
 struct event_queue {
 	u8 event[MAXQUEUELEN];
@@ -258,6 +272,7 @@
 	struct rndis_params *params;
 	atomic_t connected;
 	bool data_interface_up;
+	enum rndis_class_id rndis_id;
 
 	const struct usb_endpoint_descriptor *in_ep_desc_backup;
 	const struct usb_endpoint_descriptor *out_ep_desc_backup;
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 98e353d..b0d0020 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1706,6 +1706,8 @@
 
 	DBG(c->cdev, "ncm unbind\n");
 
+	opts->bound = false;
+
 	hrtimer_cancel(&ncm->task_timer);
 	tasklet_kill(&ncm->tx_tasklet);
 
@@ -1716,7 +1718,6 @@
 	usb_ep_free_request(ncm->notify, ncm->notify_req);
 
 	gether_cleanup(netdev_priv(opts->net));
-	opts->bound = false;
 }
 
 static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
diff --git a/drivers/usb/gadget/function/f_qdss.h b/drivers/usb/gadget/function/f_qdss.h
index 4ba2e9b..72edb90 100644
--- a/drivers/usb/gadget/function/f_qdss.h
+++ b/drivers/usb/gadget/function/f_qdss.h
@@ -31,6 +31,9 @@
 	u32 peer_pipe_idx;
 	unsigned long usb_bam_handle;
 	struct sps_mem_buffer *data_fifo;
+	unsigned long qdss_bam_iova;
+	phys_addr_t qdss_bam_phys;
+	u32 qdss_bam_size;
 };
 
 struct gqdss {
diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h
index 4f47289..0468459 100644
--- a/drivers/usb/gadget/function/u_ether_configfs.h
+++ b/drivers/usb/gadget/function/u_ether_configfs.h
@@ -35,6 +35,11 @@
 		struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);	\
 		int result;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \
 		mutex_unlock(&opts->lock);				\
@@ -48,6 +53,11 @@
 		struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);	\
 		int ret;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		if (opts->refcnt) {					\
 			mutex_unlock(&opts->lock);			\
@@ -70,6 +80,11 @@
 		struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);	\
 		int result;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \
 		mutex_unlock(&opts->lock);				\
@@ -83,6 +98,11 @@
 		struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);	\
 		int ret;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		if (opts->refcnt) {					\
 			mutex_unlock(&opts->lock);			\
@@ -105,6 +125,11 @@
 		struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);	\
 		unsigned qmult;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		qmult = gether_get_qmult(opts->net);			\
 		mutex_unlock(&opts->lock);				\
@@ -118,6 +143,11 @@
 		u8 val;							\
 		int ret;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		if (opts->refcnt) {					\
 			ret = -EBUSY;					\
@@ -144,6 +174,11 @@
 		struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);	\
 		int ret;						\
 									\
+		if (opts->bound == false) {		\
+			pr_err("Gadget function do not bind yet.\n");	\
+			return -ENODEV;			\
+		}							\
+									\
 		mutex_lock(&opts->lock);				\
 		ret = gether_get_ifname(opts->net, page, PAGE_SIZE);	\
 		mutex_unlock(&opts->lock);				\
diff --git a/drivers/usb/gadget/function/u_qdss.c b/drivers/usb/gadget/function/u_qdss.c
index 06eecd1..b4353ac 100644
--- a/drivers/usb/gadget/function/u_qdss.c
+++ b/drivers/usb/gadget/function/u_qdss.c
@@ -47,6 +47,8 @@
 	int			idx;
 	struct usb_qdss_bam_connect_info bam_info;
 	struct usb_gadget *gadget;
+	struct device *dev;
+	int ret;
 
 	pr_debug("set_qdss_data_connection\n");
 
@@ -57,6 +59,7 @@
 
 	gadget = qdss->gadget;
 	usb_bam_type = usb_bam_get_bam_type(gadget->name);
+	dev = gadget->dev.parent;
 
 	bam_info = qdss->bam_info;
 	/* There is only one qdss pipe, so the pipe number can be set to 0 */
@@ -68,6 +71,23 @@
 	}
 
 	if (enable) {
+		ret = get_qdss_bam_info(usb_bam_type, idx,
+				&bam_info.qdss_bam_phys,
+				&bam_info.qdss_bam_size);
+		if (ret) {
+			pr_err("%s(): failed to get qdss bam info err(%d)\n",
+								__func__, ret);
+			return ret;
+		}
+
+		bam_info.qdss_bam_iova = dma_map_resource(dev->parent,
+				bam_info.qdss_bam_phys, bam_info.qdss_bam_size,
+				DMA_BIDIRECTIONAL, 0);
+		if (!bam_info.qdss_bam_iova) {
+			pr_err("dma_map_resource failed\n");
+			return -ENOMEM;
+		}
+
 		usb_bam_alloc_fifos(usb_bam_type, idx);
 		bam_info.data_fifo =
 			kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL);
@@ -76,25 +96,34 @@
 			usb_bam_free_fifos(usb_bam_type, idx);
 			return -ENOMEM;
 		}
+
+		pr_debug("%s(): qdss_bam: iova:%lx p_addr:%lx size:%x\n",
+				__func__, bam_info.qdss_bam_iova,
+				(unsigned long)bam_info.qdss_bam_phys,
+				bam_info.qdss_bam_size);
+
 		get_bam2bam_connection_info(usb_bam_type, idx,
 				&bam_info.usb_bam_pipe_idx,
 				NULL, bam_info.data_fifo, NULL);
 
 		alloc_sps_req(qdss->port.data);
 		msm_data_fifo_config(qdss->port.data,
-					bam_info.data_fifo->phys_base,
-					bam_info.data_fifo->size,
-					bam_info.usb_bam_pipe_idx);
+			bam_info.data_fifo->iova,
+			bam_info.data_fifo->size,
+			bam_info.usb_bam_pipe_idx);
 		init_data(qdss->port.data);
 
 		res = usb_bam_connect(usb_bam_type, idx,
-					&(bam_info.usb_bam_pipe_idx));
+					&(bam_info.usb_bam_pipe_idx),
+					bam_info.qdss_bam_iova);
 	} else {
-		kfree(bam_info.data_fifo);
 		res = usb_bam_disconnect_pipe(usb_bam_type, idx);
 		if (res)
 			pr_err("usb_bam_disconnection error\n");
+		dma_unmap_resource(dev->parent, bam_info.qdss_bam_iova,
+				bam_info.qdss_bam_size, DMA_BIDIRECTIONAL, 0);
 		usb_bam_free_fifos(usb_bam_type, idx);
+		kfree(bam_info.data_fifo);
 	}
 
 	return res;
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 588546a..c7596a7 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -220,7 +220,15 @@
 	 * 3. xhci_plat is grandchild of a pci device (dwc3-pci)
 	 */
 	sysdev = &pdev->dev;
-	if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node)
+	/*
+	 * If sysdev->parent->parent is available and part of IOMMU group
+	 * (indicating possible usage of SMMU enablement), then use
+	 * sysdev->parent->parent as sysdev.
+	 */
+	if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node &&
+		sysdev->parent->parent && sysdev->parent->parent->iommu_group)
+		sysdev = sysdev->parent->parent;
+	else if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node)
 		sysdev = sysdev->parent;
 #ifdef CONFIG_PCI
 	else if (sysdev->parent && sysdev->parent->parent &&
@@ -316,7 +324,7 @@
 	if (device_property_read_u32(&pdev->dev, "xhci-imod-value", &imod))
 		imod = 0;
 
-	if (device_property_read_u32(sysdev, "usb-core-id", &xhci->core_id))
+	if (device_property_read_u32(&pdev->dev, "usb-core-id", &xhci->core_id))
 		xhci->core_id = -EINVAL;
 
 	hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 0091f41..56b2a6d 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -2099,7 +2099,6 @@
 		if (pd->current_pr == PR_SINK) {
 			usbpd_set_state(pd, PE_SNK_STARTUP);
 		} else if (pd->current_pr == PR_SRC) {
-			enable_vbus(pd);
 			if (!pd->vconn_enabled &&
 					pd->typec_mode ==
 					POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE) {
@@ -2109,6 +2108,7 @@
 				else
 					pd->vconn_enabled = true;
 			}
+			enable_vbus(pd);
 
 			usbpd_set_state(pd, PE_SRC_STARTUP);
 		}
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c
index 7e7c76c..8134579 100644
--- a/drivers/usb/phy/phy-msm-ssusb-qmp.c
+++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c
@@ -152,6 +152,9 @@
 	{
 		.compatible = "qcom,usb-ssphy-qmp-dp-combo",
 	},
+	{
+		.compatible = "qcom,usb-ssphy-qmp-usb3-or-dp",
+	},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, msm_usb_id_table);
@@ -177,10 +180,11 @@
 static void msm_ssusb_qmp_clamp_enable(struct msm_ssphy_qmp *phy, bool val)
 {
 	switch (phy->phy.type) {
-	case USB_PHY_TYPE_USB3_DP:
+	case USB_PHY_TYPE_USB3_AND_DP:
 		writel_relaxed(!val, phy->base +
 			phy->phy_reg[USB3_PCS_MISC_CLAMP_ENABLE]);
 		break;
+	case USB_PHY_TYPE_USB3_OR_DP:
 	case USB_PHY_TYPE_USB3:
 		writel_relaxed(!!val, phy->vls_clamp_reg);
 		break;
@@ -345,7 +349,7 @@
 	usb_qmp_powerup_phy(phy);
 
 	switch (phy->phy.type) {
-	case USB_PHY_TYPE_USB3_DP:
+	case USB_PHY_TYPE_USB3_AND_DP:
 		/* override hardware control for reset of qmp phy */
 		writel_relaxed(SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
 			SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET,
@@ -366,7 +370,7 @@
 		writel_relaxed(0x00,
 			phy->base + phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]);
 		break;
-	case  USB_PHY_TYPE_USB3:
+	case  USB_PHY_TYPE_USB3_OR_DP:
 		if (val > 0) {
 			dev_err(phy->phy.dev,
 				"USB QMP PHY: Update TYPEC CTRL(%d)\n", val);
@@ -375,7 +379,8 @@
 		}
 		break;
 	default:
-		dev_err(phy->phy.dev, "portselect: Unknown USB QMP PHY type\n");
+		dev_dbg(phy->phy.dev, "no portselect for phy type %d\n",
+					phy->phy.type);
 		break;
 	}
 
@@ -386,7 +391,7 @@
 static void usb_qmp_powerup_phy(struct msm_ssphy_qmp *phy)
 {
 	switch (phy->phy.type) {
-	case USB_PHY_TYPE_USB3_DP:
+	case USB_PHY_TYPE_USB3_AND_DP:
 		/* power up USB3 and DP common logic block */
 		writel_relaxed(0x01,
 			phy->base + phy->phy_reg[USB3_DP_COM_POWER_DOWN_CTRL]);
@@ -399,6 +404,7 @@
 		 */
 
 		/* intentional fall-through */
+	case USB_PHY_TYPE_USB3_OR_DP:
 	case USB_PHY_TYPE_USB3:
 		/* power up USB3 PHY */
 		writel_relaxed(0x01,
@@ -453,7 +459,7 @@
 	}
 
 	/* perform software reset of PHY common logic */
-	if (phy->phy.type == USB_PHY_TYPE_USB3_DP)
+	if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP)
 		writel_relaxed(0x00,
 			phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]);
 
@@ -797,7 +803,11 @@
 	phy->phy.type = USB_PHY_TYPE_USB3;
 	if (of_device_is_compatible(dev->of_node,
 			"qcom,usb-ssphy-qmp-dp-combo"))
-		phy->phy.type = USB_PHY_TYPE_USB3_DP;
+		phy->phy.type = USB_PHY_TYPE_USB3_AND_DP;
+
+	if (of_device_is_compatible(dev->of_node,
+			"qcom,usb-ssphy-qmp-usb-or-dp"))
+		phy->phy.type = USB_PHY_TYPE_USB3_OR_DP;
 
 	ret = msm_ssphy_qmp_get_clks(phy, dev);
 	if (ret)
@@ -810,7 +820,7 @@
 		goto err;
 	}
 
-	if (phy->phy.type == USB_PHY_TYPE_USB3_DP) {
+	if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP) {
 		phy->global_phy_reset = devm_reset_control_get(dev,
 						"global_phy_reset");
 		if (IS_ERR(phy->global_phy_reset)) {
@@ -871,7 +881,7 @@
 		goto err;
 	}
 
-	if (phy->phy.type == USB_PHY_TYPE_USB3) {
+	if (phy->phy.type != USB_PHY_TYPE_USB3_AND_DP) {
 		res = platform_get_resource_byname(pdev,
 				IORESOURCE_MEM, "vls_clamp_reg");
 		phy->vls_clamp_reg = devm_ioremap_resource(dev, res);
@@ -978,7 +988,7 @@
 	phy->phy.notify_connect		= msm_ssphy_qmp_notify_connect;
 	phy->phy.notify_disconnect	= msm_ssphy_qmp_notify_disconnect;
 
-	if (phy->phy.type == USB_PHY_TYPE_USB3_DP)
+	if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP)
 		phy->phy.reset		= msm_ssphy_qmp_dp_combo_reset;
 	else
 		phy->phy.reset		= msm_ssphy_qmp_reset;
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 405aed5..46ee6da 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -117,6 +117,19 @@
 };
 
 /**
+* enum ipa_vlan_ifaces - vlan interfaces types
+* @IPA_VLAN_IF_EMAC: used for EMAC ethernet device
+* @IPA_VLAN_IF_RNDIS: used for RNDIS USB device
+* @IPA_VLAN_IF_ECM: used for ECM USB device
+*/
+enum ipa_vlan_ifaces {
+	IPA_VLAN_IF_EMAC,
+	IPA_VLAN_IF_RNDIS,
+	IPA_VLAN_IF_ECM,
+	IPA_VLAN_IF_MAX
+};
+
+/**
  * struct ipa_ep_cfg_nat - NAT configuration in IPA end-point
  * @nat_en:	This defines the default NAT mode for the pipe: in case of
  *		filter miss - the default NAT mode defines the NATing operation
@@ -1585,10 +1598,18 @@
  * Returns: 0 on success, negative on failure
  */
 int ipa_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs);
-
 int ipa_get_smmu_params(struct ipa_smmu_in_params *in,
 	struct ipa_smmu_out_params *out);
-
+/**
+ * ipa_is_vlan_mode - check if a LAN driver should load in VLAN mode
+ * @iface - type of vlan capable device
+ * @res - query result: true for vlan mode, false for non vlan mode
+ *
+ * API must be called after ipa_is_ready() returns true, otherwise it will fail
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res);
 #else /* (CONFIG_IPA || CONFIG_IPA3) */
 
 /*
@@ -2382,6 +2403,11 @@
 {
 	return -EPERM;
 }
+
+static inline int ipa_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res)
+{
+	return -EPERM;
+}
 #endif /* (CONFIG_IPA || CONFIG_IPA3) */
 
 #endif /* _IPA_H_ */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 4f56e98..b2eb2d0 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -1120,12 +1120,12 @@
 int msm_ep_config(struct usb_ep *ep);
 int msm_ep_unconfig(struct usb_ep *ep);
 void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enable);
-int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr, u32 size,
+int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr, u32 size,
 	u8 dst_pipe_idx);
 bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget);
 int msm_dwc3_reset_dbm_ep(struct usb_ep *ep);
 #else
-static inline int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
+static inline int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr,
 	u32 size, u8 dst_pipe_idx)
 {	return -ENODEV; }
 
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 742ef8d..64aa52e 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -45,7 +45,8 @@
 	USB_PHY_TYPE_UNDEFINED,
 	USB_PHY_TYPE_USB2,
 	USB_PHY_TYPE_USB3,
-	USB_PHY_TYPE_USB3_DP,
+	USB_PHY_TYPE_USB3_OR_DP,
+	USB_PHY_TYPE_USB3_AND_DP,
 };
 
 /* OTG defines lots of enumeration states before device reset */
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index 1b0ca4a..84d7549 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -245,10 +245,13 @@
  *
  * @bam_pipe_idx - allocated pipe index.
  *
+ * @iova - IPA address of USB peer BAM (i.e. QDSS BAM)
+ *
  * @return 0 on success, negative value on error
  *
  */
-int usb_bam_connect(enum usb_ctrl bam_type, int idx, u32 *bam_pipe_idx);
+int usb_bam_connect(enum usb_ctrl bam_type, int idx, u32 *bam_pipe_idx,
+						unsigned long iova);
 
 /**
  * Connect USB-to-IPA SPS connection.
@@ -430,12 +433,14 @@
 
 /* Frees memory for data fifo and descriptor fifos. */
 int usb_bam_free_fifos(enum usb_ctrl cur_bam, u8 idx);
-
+int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
+			phys_addr_t *p_addr, u32 *bam_size);
 bool msm_bam_hsic_lpm_ok(void);
 bool msm_bam_hsic_host_pipe_empty(void);
 bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable);
 #else
-static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx)
+static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx,
+							unsigned long iova)
 {
 	return -ENODEV;
 }
@@ -529,6 +534,11 @@
 	return false;
 }
 
+static int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
+				phys_addr_t *p_addr, u32 *bam_size)
+{
+	return false;
+}
 static inline bool msm_bam_hsic_lpm_ok(void) { return true; }
 static inline bool msm_bam_hsic_host_pipe_empty(void) { return true; }
 static inline bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable)
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index d3b9a33..ef07f78 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -819,13 +819,17 @@
  * IPA_HDR_L2_NONE: L2 header which isn't Ethernet II and isn't 802_3
  * IPA_HDR_L2_ETHERNET_II: L2 header of type Ethernet II
  * IPA_HDR_L2_802_3: L2 header of type 802_3
+ * IPA_HDR_L2_802_1Q: L2 header of type 802_1Q
  */
 enum ipa_hdr_l2_type {
 	IPA_HDR_L2_NONE,
 	IPA_HDR_L2_ETHERNET_II,
 	IPA_HDR_L2_802_3,
+	IPA_HDR_L2_802_1Q,
 };
-#define IPA_HDR_L2_MAX (IPA_HDR_L2_802_3 + 1)
+#define IPA_HDR_L2_MAX (IPA_HDR_L2_802_1Q + 1)
+
+#define IPA_HDR_L2_802_1Q IPA_HDR_L2_802_1Q
 
 /**
  * enum ipa_hdr_l2_type - Processing context type
diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h
index 9a767dd..cabf0a8 100644
--- a/include/uapi/media/cam_defs.h
+++ b/include/uapi/media/cam_defs.h
@@ -17,6 +17,9 @@
 #define CAM_SD_SHUTDOWN                         (CAM_COMMON_OPCODE_BASE + 0x7)
 #define CAM_COMMON_OPCODE_MAX                   (CAM_COMMON_OPCODE_BASE + 0x8)
 
+#define CAM_EXT_OPCODE_BASE                     0x200
+#define CAM_CONFIG_DEV_EXTERNAL                 (CAM_EXT_OPCODE_BASE + 0x1)
+
 /* camera handle type */
 #define CAM_HANDLE_USER_POINTER                 1
 #define CAM_HANDLE_MEM_HANDLE                   2
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index 6846b8f..3f1facd 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -424,6 +424,7 @@
  */
 struct cam_req_mgr_message {
 	int32_t session_hdl;
+	int32_t reserved;
 	union {
 		struct cam_req_mgr_error_msg err_msg;
 		struct cam_req_mgr_frame_msg frame_msg;