Merge "defconfig: Enable CONFIG_PAGE_POISONING for sdm845" into msm-4.9
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
index e53b691..04b624b 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
@@ -16,6 +16,10 @@
   Should be "active" and "sleep" for the pin confuguration when core is active
   or when entering sleep state.
 
+Optional properties:
+- qcom,bus-mas: contains the bus master id needed to put in bus bandwidth votes
+		for inter-connect buses.
+
 Example:
 qupv3_uart11: qcom,qup_uart@0xa88000 {
 	compatible = "qcom,msm-geni-uart";
@@ -29,4 +33,5 @@
 	pinctrl-0 = <&qup_1_uart_3_active>;
 	pinctrl-1 = <&qup_1_uart_3_sleep>;
 	interrupts = <0 355 0>;
+	qcom,bus-mas = <MASTER_BLSP_2>;
 };
diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
index 080d4da..8bead0d 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
@@ -25,12 +25,18 @@
 			interrupt generated by the LMH DCVSh hardware. LMH
 			DCVSh hardware will generate this interrupt whenever
 			it makes a new cpu DCVS decision.
+- qcom,affinity:
+	Usage: Required
+	Value type: <u32>
+	Definition: Should specify the cluster affinity this hardware
+			corresponds to.
 
 Example:
 
 	lmh_dcvs0: qcom,limits-dcvs@0 {
 		compatible = "qcom,msm-hw-limits";
 		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,affinity = <0>;
 	};
 
 	CPU0: cpu@0 {
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index 7c496f1..15db8da 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -136,6 +136,7 @@
 			interrupt-names = "eoc-int-en-set";
 			qcom,adc-bit-resolution = <15>;
 			qcom,adc-vdd-reference = <1875>;
+			#thermal-sensor-cells = <1>;
 
 			chan@6 {
 				label = "die_temp";
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 539685a..923804f 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -232,6 +232,25 @@
 						 <12000 2250>; /* 12V @ 2.25A */
 		};
 
+		bcl_sensor: bcl@4200 {
+			compatible = "qcom,msm-bcl-lmh";
+			reg = <0x4200 0xff>,
+				<0x4300 0xff>;
+			reg-names = "fg_user_adc",
+					"fg_lmh";
+			interrupts = <0x2 0x42 0x0 IRQ_TYPE_NONE>,
+					<0x2 0x42 0x1 IRQ_TYPE_NONE>,
+					<0x2 0x42 0x2 IRQ_TYPE_NONE>,
+					<0x2 0x42 0x3 IRQ_TYPE_NONE>,
+					<0x2 0x42 0x4 IRQ_TYPE_NONE>;
+			interrupt-names = "bcl-high-ibat",
+						"bcl-very-high-ibat",
+						"bcl-low-vbat",
+						"bcl-very-low-vbat",
+						"bcl-crit-low-vbat";
+			#thermal-sensor-cells = <1>;
+		};
+
 		pmi8998_rradc: rradc@4500 {
 			compatible = "qcom,rradc";
 			reg = <0x4500 0x100>;
@@ -651,3 +670,130 @@
 		};
 	};
 };
+
+&thermal_zones {
+	ibat-high {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "step_wise";
+		thermal-sensors = <&bcl_sensor 0>;
+
+		trips {
+			ibat_high: low-ibat {
+				temperature = <4200>;
+				hysteresis = <200>;
+				type = "passive";
+			};
+		};
+	};
+	ibat-vhigh {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "step_wise";
+		thermal-sensors = <&bcl_sensor 1>;
+
+		trips {
+			ibat_vhigh: ibat_vhigh {
+				temperature = <4300>;
+				hysteresis = <100>;
+				type = "passive";
+			};
+		};
+	};
+	vbat {
+		polling-delay-passive = <100>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_cap";
+		thermal-sensors = <&bcl_sensor 2>;
+		tracks-low;
+
+		trips {
+			low_vbat: low-vbat {
+				temperature = <3300>;
+				hysteresis = <100>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			vbat_cpu4 {
+				trip = <&low_vbat>;
+				cooling-device = <&CPU4 22 22>;
+			};
+			vbat_cpu5 {
+				trip = <&low_vbat>;
+				cooling-device = <&CPU5 22 22>;
+			};
+			vbat_map6 {
+				trip = <&low_vbat>;
+				cooling-device = <&CPU6 22 22>;
+			};
+			vbat_map7 {
+				trip = <&low_vbat>;
+				cooling-device = <&CPU7 22 22>;
+			};
+		};
+	};
+	vbat_low {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_cap";
+		thermal-sensors = <&bcl_sensor 3>;
+		tracks-low;
+
+		trips {
+			low-vbat {
+				temperature = <3100>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+	};
+	vbat_too_low {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_cap";
+		thermal-sensors = <&bcl_sensor 4>;
+		tracks-low;
+
+		trips {
+			low-vbat {
+				temperature = <2900>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+	};
+	soc {
+		polling-delay-passive = <100>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_cap";
+		thermal-sensors = <&bcl_sensor 5>;
+		tracks-low;
+
+		trips {
+			low_soc: low-soc {
+				temperature = <10>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			soc_cpu4 {
+				trip = <&low_soc>;
+				cooling-device = <&CPU4 22 22>;
+			};
+			soc_cpu5 {
+				trip = <&low_soc>;
+				cooling-device = <&CPU5 22 22>;
+			};
+			soc_map6 {
+				trip = <&low_soc>;
+				cooling-device = <&CPU6 22 22>;
+			};
+			soc_map7 {
+				trip = <&low_soc>;
+				cooling-device = <&CPU7 22 22>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index e98a973..6f35bf7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -267,6 +267,7 @@
 		qcom,scale-function = <4>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 
 	chan@4d {
@@ -278,6 +279,7 @@
 		qcom,scale-function = <2>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 
 	chan@4f {
@@ -289,6 +291,7 @@
 		qcom,scale-function = <2>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 
 	chan@51 {
@@ -300,6 +303,7 @@
 		qcom,scale-function = <2>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 };
 
@@ -313,48 +317,30 @@
 		qcom,hw-settle-time = <0>;
 		qcom,btm-channel-number = <0x60>;
 	};
+};
 
-	chan@4d {
-		label = "msm_therm";
-		reg = <0x4d>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <2>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x68>;
-		qcom,thermal-node;
+&thermal_zones {
+	xo-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x4c>;
 	};
 
-	chan@51 {
-		label = "quiet_therm";
-		reg = <0x51>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <2>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x70>;
-		qcom,thermal-node;
+	msm-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x4d>;
 	};
 
-	chan@4c {
-		label = "xo_therm";
-		reg = <0x4c>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <4>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x78>;
-		qcom,thermal-node;
+	pa-therm1-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x4f>;
 	};
 
-	chan@4f {
-		label = "pa_therm1";
-		reg = <0x4f>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <2>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x80>;
-		qcom,thermal-node;
+	quiet-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x51>;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 3f2317a..bfbaabb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -74,6 +74,7 @@
 		qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
 
 		qcom,tsens-name = "tsens_tz_sensor12";
+		#cooling-cells = <2>;
 
 		clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK>,
 			<&clock_gcc GCC_GPU_CFG_AHB_CLK>,
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 6a4f19a..faa0b5e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -245,6 +245,7 @@
 		qcom,scale-function = <4>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 
 	chan@4d {
@@ -256,6 +257,7 @@
 		qcom,scale-function = <2>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 
 	chan@4f {
@@ -267,6 +269,7 @@
 		qcom,scale-function = <2>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 
 	chan@51 {
@@ -278,6 +281,7 @@
 		qcom,scale-function = <2>;
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
 	};
 };
 
@@ -291,48 +295,30 @@
 		qcom,hw-settle-time = <0>;
 		qcom,btm-channel-number = <0x60>;
 	};
+};
 
-	chan@4d {
-		label = "msm_therm";
-		reg = <0x4d>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <2>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x68>;
-		qcom,thermal-node;
+&thermal_zones {
+	xo-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x4c>;
 	};
 
-	chan@51 {
-		label = "quiet_therm";
-		reg = <0x51>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <2>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x70>;
-		qcom,thermal-node;
+	msm-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x4d>;
 	};
 
-	chan@4c {
-		label = "xo_therm";
-		reg = <0x4c>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <4>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x78>;
-		qcom,thermal-node;
+	pa-therm1-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x4f>;
 	};
 
-	chan@4f {
-		label = "pa_therm1";
-		reg = <0x4f>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "ratiometric";
-		qcom,scale-function = <2>;
-		qcom,hw-settle-time = <2>;
-		qcom,btm-channel-number = <0x80>;
-		qcom,thermal-node;
+	quiet-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8998_vadc 0x51>;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
index 1c31a7a..dd0d08e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
@@ -10,6 +10,8 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/msm/msm-bus-ids.h>
+
 &soc {
 	/* QUPv3 South instances */
 
@@ -30,6 +32,7 @@
 		pinctrl-1 = <&qupv3_se6_4uart_sleep>;
 		interrupts = <GIC_SPI 607 0>;
 		status = "disabled";
+		qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
 	};
 
 	qupv3_se7_4uart: qcom,qup_uart@0x89c000 {
@@ -45,6 +48,7 @@
 		pinctrl-1 = <&qupv3_se7_4uart_sleep>;
 		interrupts = <GIC_SPI 608 0>;
 		status = "disabled";
+		qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
 	};
 
 	/* I2C */
@@ -336,6 +340,7 @@
 		pinctrl-names = "default", "sleep";
 		pinctrl-0 = <&qupv3_se9_2uart_active>;
 		pinctrl-1 = <&qupv3_se9_2uart_sleep>;
+		qcom,bus-mas = <MSM_BUS_MASTER_BLSP_2>;
 		interrupts = <GIC_SPI 354 0>;
 		status = "disabled";
 	};
@@ -353,6 +358,7 @@
 		pinctrl-0 = <&qupv3_se10_2uart_active>;
 		pinctrl-1 = <&qupv3_se10_2uart_sleep>;
 		interrupts = <GIC_SPI 355 0>;
+		qcom,bus-mas = <MSM_BUS_MASTER_BLSP_2>;
 		status = "disabled";
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 24eeeec..92add14 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -22,6 +22,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/soc/qcom,tcs-mbox.h>
 #include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM845";
@@ -47,6 +48,8 @@
 			efficiency = <1024>;
 			cache-size = <0x8000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_0>;
 			L2_0: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -78,6 +81,8 @@
 			efficiency = <1024>;
 			cache-size = <0x8000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_100>;
 			L2_100: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -103,6 +108,8 @@
 			efficiency = <1024>;
 			cache-size = <0x8000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_200>;
 			L2_200: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -128,6 +135,8 @@
 			efficiency = <1024>;
 			cache-size = <0x8000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_300>;
 			L2_300: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -153,6 +162,8 @@
 			efficiency = <1740>;
 			cache-size = <0x20000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_400>;
 			L2_400: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -178,6 +189,8 @@
 			efficiency = <1740>;
 			cache-size = <0x20000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_500>;
 			L2_500: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -203,6 +216,8 @@
 			efficiency = <1740>;
 			cache-size = <0x20000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_600>;
 			L2_600: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -228,6 +243,8 @@
 			efficiency = <1740>;
 			cache-size = <0x20000>;
 			cpu-release-addr = <0x0 0x90000000>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
+			#cooling-cells = <2>;
 			next-level-cache = <&L2_700>;
 			L2_700: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -2070,6 +2087,8 @@
 		qcom,modem-cfg-emb-pipe-flt;
 		qcom,ipa-wdi2;
 		qcom,use-64-bit-dma-mask;
+		qcom,arm-smmu;
+		qcom,smmu-s1-bypass;
 		qcom,bandwidth-vote-for-ipa;
 		qcom,msm-bus,name = "ipa";
 		qcom,msm-bus,num-cases = <4>;
@@ -2181,6 +2200,23 @@
 			compatible = "qcom,smp2pgpio-map-ipa-1-in";
 			gpios = <&smp2pgpio_ipa_1_in 0 0>;
 		};
+
+		ipa_smmu_ap: ipa_smmu_ap {
+			compatible = "qcom,ipa-smmu-ap-cb";
+			iommus = <&apps_smmu 0x720>;
+			qcom,iova-mapping = <0x20000000 0x40000000>;
+		};
+
+		ipa_smmu_wlan: ipa_smmu_wlan {
+			compatible = "qcom,ipa-smmu-wlan-cb";
+			iommus = <&apps_smmu 0x721>;
+		};
+
+		ipa_smmu_uc: ipa_smmu_uc {
+			compatible = "qcom,ipa-smmu-uc-cb";
+			iommus = <&apps_smmu 0x722>;
+			qcom,iova-mapping = <0x40000000 0x20000000>;
+		};
 	};
 
 	qcom,ipa_fws {
@@ -2266,7 +2302,7 @@
 		aoss0-ts0-h {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			thermal-sensors = <&tsens0 0>;
 			trips {
 				active-config0 {
@@ -2280,7 +2316,7 @@
 		cpu0-silver-ts0-h {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			thermal-sensors = <&tsens0 1>;
 			trips {
 				active-config0 {
@@ -2294,7 +2330,7 @@
 		cpu1-silver-ts0-h {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			thermal-sensors = <&tsens0 2>;
 			trips {
 				active-config0 {
@@ -2308,7 +2344,7 @@
 		cpu2-silver-ts0-h {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			thermal-sensors = <&tsens0 3>;
 			trips {
 				active-config0 {
@@ -2323,7 +2359,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 4>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2337,7 +2373,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 5>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2351,7 +2387,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 6>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2365,7 +2401,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 7>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2379,7 +2415,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 8>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2393,7 +2429,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 9>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2407,7 +2443,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 10>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2421,7 +2457,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 11>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2434,7 +2470,7 @@
 		gpu1-ts0-h {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			thermal-sensors = <&tsens0 12>;
 			trips {
 				active-config0 {
@@ -2449,7 +2485,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 0>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2463,7 +2499,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 1>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2479,7 +2515,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 2>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2493,7 +2529,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 3>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2507,7 +2543,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 4>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2521,7 +2557,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 5>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2535,7 +2571,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 6>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2549,7 +2585,7 @@
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 7>;
-			thermal-governor = "step_wise";
+			thermal-governor = "user_space";
 			trips {
 				active-config0 {
 					temperature = <65000>;
@@ -2558,6 +2594,709 @@
 				};
 			};
 		};
+
+		gpu0 {
+			polling-delay-passive = <10>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 11>;
+			thermal-governor = "step_wise";
+			trips {
+				gpu0_trip: gpu0-trip {
+					temperature = <95000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				gpu0_cdev {
+					trip = <&gpu0_trip>;
+					cooling-device =
+						<&msm_gpu 1 THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu1 {
+			polling-delay-passive = <10>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens0 12>;
+			thermal-governor = "step_wise";
+			trips {
+				gpu1_trip: gpu1-trip {
+					temperature = <95000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				gpu1_cdev {
+					trip = <&gpu1_trip>;
+					cooling-device =
+						<&msm_gpu 1 THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		pop-mem {
+			polling-delay-passive = <10>;
+			polling-delay = <0>;
+			thermal-sensors = <&tsens1 2>;
+			thermal-governor = "step_wise";
+			trips {
+				pop_trip: pop-trip {
+					temperature = <95000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				pop_cdev {
+					trip = <&pop_trip>;
+					cooling-device =
+						<&CPU4 1 THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		aoss0-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 0>;
+			tracks-low;
+			trips {
+				aoss0_trip: aoss0-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&aoss0_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&aoss0_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&aoss0_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu0-silver-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 1>;
+			tracks-low;
+			trips {
+				cpu0_trip: cpu0-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpu0_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpu0_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpu0_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu1-silver-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 2>;
+			tracks-low;
+			trips {
+				cpu1_trip: cpu1-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpu1_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpu1_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpu1_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu2-silver-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 3>;
+			tracks-low;
+			trips {
+				cpu2_trip: cpu2-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpu2_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpu2_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpu2_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu3-silver-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 4>;
+			tracks-low;
+			trips {
+				cpu3_trip: cpu3-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpu3_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpu3_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpu3_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		kryo-l3-0-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 5>;
+			tracks-low;
+			trips {
+				l3_0_trip: l3-0-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&l3_0_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&l3_0_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&l3_0_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		kryo-l3-1-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 6>;
+			tracks-low;
+			trips {
+				l3_1_trip: l3-1-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&l3_1_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&l3_1_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&l3_1_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu0-gold-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 7>;
+			tracks-low;
+			trips {
+				cpug0_trip: cpug0-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpug0_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpug0_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpug0_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu1-gold-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 8>;
+			tracks-low;
+			trips {
+				cpug1_trip: cpug1-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpug1_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpug1_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpug1_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu2-gold-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 9>;
+			tracks-low;
+			trips {
+				cpug2_trip: cpug2-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpug2_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpug2_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpug2_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		cpu3-gold-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 9>;
+			tracks-low;
+			trips {
+				cpug3_trip: cpug3-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&cpug3_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&cpug3_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&cpug3_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		gpu0-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 10>;
+			tracks-low;
+			trips {
+				gpu0_trip_l: gpu0-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&gpu0_trip_l>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&gpu0_trip_l>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&gpu0_trip_l>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		gpu1-ts0-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens0 11>;
+			tracks-low;
+			trips {
+				gpu1_trip_l: gpu1-trip_l {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&gpu1_trip_l>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&gpu1_trip_l>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&gpu1_trip_l>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		aoss1-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 0>;
+			tracks-low;
+			trips {
+				aoss1_trip: aoss1-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&aoss1_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&aoss1_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&aoss1_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		mdm-dsp-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 1>;
+			tracks-low;
+			trips {
+				dsp_trip: dsp-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&dsp_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&dsp_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&dsp_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		ddr-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 2>;
+			tracks-low;
+			trips {
+				ddr_trip: ddr-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&ddr_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&ddr_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&ddr_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		wlan-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 3>;
+			tracks-low;
+			trips {
+				wlan_trip: wlan-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&wlan_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&wlan_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&wlan_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		compute-hvx-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 4>;
+			tracks-low;
+			trips {
+				hvx_trip: hvx-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&hvx_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&hvx_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&hvx_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		camera-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 5>;
+			tracks-low;
+			trips {
+				camera_trip: camera-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&camera_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&camera_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&camera_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		mmss-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 6>;
+			tracks-low;
+			trips {
+				mmss_trip: mmss-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&mmss_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&mmss_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&mmss_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		mdm-core-ts1-l {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "low_limits_floor";
+			thermal-sensors = <&tsens1 7>;
+			tracks-low;
+			trips {
+				mdm_trip: mdm-trip {
+					temperature = <5000>;
+					hysteresis = <5000>;
+					type = "passive";
+				};
+			};
+			cooling-maps {
+				cpu0_vdd_cdev {
+					trip = <&mdm_trip>;
+					cooling-device = <&CPU0 12 12>;
+				};
+				cpu4_vdd_cdev {
+					trip = <&mdm_trip>;
+					cooling-device = <&CPU4 12 12>;
+				};
+				gpu_vdd_cdev {
+					trip = <&mdm_trip>;
+					cooling-device = <&msm_gpu 4 4>;
+				};
+			};
+		};
+
+		lmh-dcvs-01 {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "user_space";
+			thermal-sensors = <&lmh_dcvs1>;
+
+			trips {
+				active-config {
+					temperature = <95000>;
+					hysteresis = <30000>;
+					type = "passive";
+				};
+			};
+		};
+
+		lmh-dcvs-00 {
+			polling-delay-passive = <0>;
+			polling-delay = <0>;
+			thermal-governor = "user_space";
+			thermal-sensors = <&lmh_dcvs0>;
+
+			trips {
+				active-config {
+					temperature = <95000>;
+					hysteresis = <30000>;
+					type = "passive";
+				};
+			};
+		};
+
 	};
 
 	tsens0: tsens@c222000 {
@@ -2583,6 +3322,22 @@
 	};
 };
 
+&clock_cpucc {
+	lmh_dcvs0: qcom,limits-dcvs@0 {
+		compatible = "qcom,msm-hw-limits";
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,affinity = <0>;
+		#thermal-sensor-cells = <0>;
+	};
+
+	lmh_dcvs1: qcom,limits-dcvs@1 {
+		compatible = "qcom,msm-hw-limits";
+		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,affinity = <1>;
+		#thermal-sensor-cells = <0>;
+	};
+};
+
 &pcie_0_gdsc {
 	status = "ok";
 };
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 852c01f..629f712 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -301,9 +301,17 @@
 CONFIG_QPNP_QNOVO=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
 CONFIG_THERMAL_QPNP=y
 CONFIG_THERMAL_QPNP_ADC_TM=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_WCD934X_CODEC=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 85fc3b5..a54995f 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -311,9 +311,17 @@
 CONFIG_QPNP_QNOVO=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
 CONFIG_THERMAL_QPNP=y
 CONFIG_THERMAL_QPNP_ADC_TM=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_WCD934X_CODEC=y
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 3b40f26..aaf4bd7 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -394,7 +394,7 @@
 {
 	struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL1];
 
-	if (!sge) {
+	if (sched_is_energy_aware() && !sge) {
 		pr_warn("Invalid sched_group_energy for Cluster%d\n", cpu);
 		return NULL;
 	}
@@ -407,7 +407,7 @@
 {
 	struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL0];
 
-	if (!sge) {
+	if (sched_is_energy_aware() && !sge) {
 		pr_warn("Invalid sched_group_energy for CPU%d\n", cpu);
 		return NULL;
 	}
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 9c26f87..e907d0d 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -773,6 +773,7 @@
 	if (*buf != 0x80) {
 		list_del(&entry->track);
 		kfree(entry);
+		entry = NULL;
 		return 1;
 	}
 
@@ -790,6 +791,7 @@
 	if (delayed_rsp_id == 0) {
 		list_del(&entry->track);
 		kfree(entry);
+		entry = NULL;
 		return 1;
 	}
 
@@ -803,6 +805,7 @@
 	if (rsp_count > 0 && rsp_count < 0x1000) {
 		list_del(&entry->track);
 		kfree(entry);
+		entry = NULL;
 		return 1;
 	}
 
@@ -1447,6 +1450,7 @@
 		dci_ops_tbl[proc].peripheral_status &= ~peripheral_mask;
 
 	/* Notify the DCI process that the peripheral DCI Channel is up */
+	mutex_lock(&driver->dci_mutex);
 	list_for_each_safe(start, temp, &driver->dci_client_list) {
 		entry = list_entry(start, struct diag_dci_client_tbl, track);
 		if (entry->client_info.token != proc)
@@ -1469,6 +1473,7 @@
 						info.si_int, stat);
 		}
 	}
+	mutex_unlock(&driver->dci_mutex);
 }
 
 static int diag_send_dci_pkt(struct diag_cmd_reg_t *entry,
@@ -1942,6 +1947,7 @@
 	reg_entry.cmd_code_hi = header->subsys_cmd_code;
 	reg_entry.cmd_code_lo = header->subsys_cmd_code;
 
+	mutex_lock(&driver->cmd_reg_mutex);
 	temp_entry = diag_cmd_search(&reg_entry, ALL_PROC);
 	if (temp_entry) {
 		reg_item = container_of(temp_entry, struct diag_cmd_reg_t,
@@ -1953,6 +1959,7 @@
 				reg_entry.cmd_code, reg_entry.subsys_id,
 				reg_entry.cmd_code_hi);
 	}
+	mutex_unlock(&driver->cmd_reg_mutex);
 
 	return ret;
 }
@@ -2684,10 +2691,12 @@
 err:
 	pr_err("diag: Could not initialize diag DCI buffers");
 	kfree(driver->apps_dci_buf);
+	driver->apps_dci_buf = NULL;
 
 	if (driver->diag_dci_wq)
 		destroy_workqueue(driver->diag_dci_wq);
 	kfree(partial_pkt.data);
+	partial_pkt.data = NULL;
 	mutex_destroy(&driver->dci_mutex);
 	mutex_destroy(&dci_log_mask_mutex);
 	mutex_destroy(&dci_event_mask_mutex);
@@ -2707,7 +2716,9 @@
 void diag_dci_exit(void)
 {
 	kfree(partial_pkt.data);
+	partial_pkt.data = NULL;
 	kfree(driver->apps_dci_buf);
+	driver->apps_dci_buf = NULL;
 	mutex_destroy(&driver->dci_mutex);
 	mutex_destroy(&dci_log_mask_mutex);
 	mutex_destroy(&dci_event_mask_mutex);
@@ -2914,22 +2925,30 @@
 				mutex_destroy(&proc_buf->health_mutex);
 				if (proc_buf->buf_primary) {
 					kfree(proc_buf->buf_primary->data);
+					proc_buf->buf_primary->data = NULL;
 					mutex_destroy(
 					   &proc_buf->buf_primary->data_mutex);
 				}
 				kfree(proc_buf->buf_primary);
+				proc_buf->buf_primary = NULL;
 				if (proc_buf->buf_cmd) {
 					kfree(proc_buf->buf_cmd->data);
+					proc_buf->buf_cmd->data = NULL;
 					mutex_destroy(
 					   &proc_buf->buf_cmd->data_mutex);
 				}
 				kfree(proc_buf->buf_cmd);
+				proc_buf->buf_cmd = NULL;
 			}
 		}
 		kfree(new_entry->dci_event_mask);
+		new_entry->dci_event_mask = NULL;
 		kfree(new_entry->dci_log_mask);
+		new_entry->dci_log_mask = NULL;
 		kfree(new_entry->buffers);
+		new_entry->buffers = NULL;
 		kfree(new_entry);
+		new_entry = NULL;
 	}
 	mutex_unlock(&driver->dci_mutex);
 	return DIAG_DCI_NO_REG;
@@ -2960,6 +2979,7 @@
 	 * masks and send the masks to peripherals
 	 */
 	kfree(entry->dci_log_mask);
+	entry->dci_log_mask = NULL;
 	diag_dci_invalidate_cumulative_log_mask(token);
 	if (token == DCI_LOCAL_PROC)
 		diag_update_userspace_clients(DCI_LOG_MASKS_TYPE);
@@ -2967,6 +2987,7 @@
 	if (ret != DIAG_DCI_NO_ERROR)
 		return ret;
 	kfree(entry->dci_event_mask);
+	entry->dci_event_mask = NULL;
 	diag_dci_invalidate_cumulative_event_mask(token);
 	if (token == DCI_LOCAL_PROC)
 		diag_update_userspace_clients(DCI_EVENT_MASKS_TYPE);
@@ -2981,6 +3002,7 @@
 			if (!list_empty(&req_entry->track))
 				list_del(&req_entry->track);
 			kfree(req_entry);
+			req_entry = NULL;
 		}
 	}
 
@@ -2996,6 +3018,7 @@
 			buf_entry->data = NULL;
 			mutex_unlock(&buf_entry->data_mutex);
 			kfree(buf_entry);
+			buf_entry = NULL;
 		} else if (buf_entry->buf_type == DCI_BUF_CMD) {
 			peripheral = buf_entry->data_source;
 			if (peripheral == APPS_DATA)
@@ -3022,14 +3045,17 @@
 			mutex_unlock(&buf_entry->data_mutex);
 			mutex_destroy(&buf_entry->data_mutex);
 			kfree(buf_entry);
+			buf_entry = NULL;
 		}
 
 		mutex_lock(&proc_buf->buf_primary->data_mutex);
 		kfree(proc_buf->buf_primary->data);
+		proc_buf->buf_primary->data = NULL;
 		mutex_unlock(&proc_buf->buf_primary->data_mutex);
 
 		mutex_lock(&proc_buf->buf_cmd->data_mutex);
 		kfree(proc_buf->buf_cmd->data);
+		proc_buf->buf_cmd->data = NULL;
 		mutex_unlock(&proc_buf->buf_cmd->data_mutex);
 
 		mutex_destroy(&proc_buf->health_mutex);
@@ -3037,13 +3063,17 @@
 		mutex_destroy(&proc_buf->buf_cmd->data_mutex);
 
 		kfree(proc_buf->buf_primary);
+		proc_buf->buf_primary = NULL;
 		kfree(proc_buf->buf_cmd);
+		proc_buf->buf_cmd = NULL;
 		mutex_unlock(&proc_buf->buf_mutex);
 	}
 	mutex_destroy(&entry->write_buf_mutex);
 
 	kfree(entry->buffers);
+	entry->buffers = NULL;
 	kfree(entry);
+	entry = NULL;
 
 	if (driver->num_dci_client == 0) {
 		diag_update_proc_vote(DIAG_PROC_DCI, VOTE_DOWN, token);
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 558e362..13ad402 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -354,8 +354,8 @@
 			ch->tbl[j].buf = NULL;
 			ch->tbl[j].len = 0;
 			ch->tbl[j].ctx = 0;
-			spin_lock_init(&(ch->lock));
 		}
+		spin_lock_init(&(ch->lock));
 	}
 
 	return 0;
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index ac8a6d0..1cf7f52 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/ratelimit.h>
@@ -218,7 +219,8 @@
 	if (!ch)
 		return;
 
-	if (!atomic_read(&ch->connected) && driver->usb_connected)
+	if (!atomic_read(&ch->connected) &&
+		driver->usb_connected && diag_mask_param())
 		diag_clear_masks(NULL);
 
 	if (ch && ch->ops && ch->ops->close)
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index ea380fb..d3dde50 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -505,6 +505,7 @@
 	int ref_count;
 	int mask_clear;
 	struct mutex diag_maskclear_mutex;
+	struct mutex diag_notifier_mutex;
 	struct mutex diagchar_mutex;
 	struct mutex diag_file_mutex;
 	wait_queue_head_t wait_q;
@@ -547,7 +548,7 @@
 	struct mutex diag_id_mutex;
 	struct mutex cmd_reg_mutex;
 	uint32_t cmd_reg_count;
-	struct mutex diagfwd_channel_mutex;
+	struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS];
 	/* Sizes that reflect memory pool sizes */
 	unsigned int poolsize;
 	unsigned int poolsize_hdlc;
@@ -666,6 +667,7 @@
 void diag_cmd_remove_reg_by_pid(int pid);
 void diag_cmd_remove_reg_by_proc(int proc);
 int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry);
+int diag_mask_param(void);
 void diag_clear_masks(struct diag_md_session_t *info);
 
 void diag_record_stats(int type, int flag);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index c44a9ea..128d6ce 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -143,6 +143,14 @@
 static struct timer_list drain_timer;
 static int timer_in_progress;
 
+/*
+ * Diag Mask clear variable
+ * Used for clearing masks upon
+ * USB disconnection and stopping ODL
+ */
+static int diag_mask_clear_param = 1;
+module_param(diag_mask_clear_param, int, 0644);
+
 struct diag_apps_data_t {
 	void *buf;
 	uint32_t len;
@@ -388,7 +396,10 @@
 
 	return ret;
 }
-
+int diag_mask_param(void)
+{
+	return diag_mask_clear_param;
+}
 void diag_clear_masks(struct diag_md_session_t *info)
 {
 	int ret;
@@ -421,14 +432,17 @@
 	if (!session_info)
 		return;
 
-	diag_clear_masks(session_info);
+	if (diag_mask_clear_param)
+		diag_clear_masks(session_info);
 
 	mutex_lock(&driver->diag_maskclear_mutex);
 	driver->mask_clear = 1;
 	mutex_unlock(&driver->diag_maskclear_mutex);
 
+	mutex_lock(&driver->diagchar_mutex);
 	session_peripheral_mask = session_info->peripheral_mask;
 	diag_md_session_close(session_info);
+	mutex_unlock(&driver->diagchar_mutex);
 	for (i = 0; i < NUM_MD_SESSIONS; i++)
 		if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask)
 			diag_mux_close_peripheral(DIAG_LOCAL_PROC, i);
@@ -701,7 +715,7 @@
 
 	list_for_each_safe(start, temp, &driver->cmd_reg_list) {
 		item = list_entry(start, struct diag_cmd_reg_t, link);
-		if (item == NULL || &item->entry == NULL) {
+		if (&item->entry == NULL) {
 			pr_err("diag: In %s, unable to search command\n",
 			       __func__);
 			return NULL;
@@ -3402,7 +3416,7 @@
 static int __init diagchar_init(void)
 {
 	dev_t dev;
-	int ret;
+	int ret, i;
 
 	pr_debug("diagfwd initializing ..\n");
 	ret = 0;
@@ -3445,10 +3459,12 @@
 	mutex_init(&driver->hdlc_disable_mutex);
 	mutex_init(&driver->diagchar_mutex);
 	mutex_init(&driver->diag_maskclear_mutex);
+	mutex_init(&driver->diag_notifier_mutex);
 	mutex_init(&driver->diag_file_mutex);
 	mutex_init(&driver->delayed_rsp_mutex);
 	mutex_init(&apps_data_mutex);
-	mutex_init(&driver->diagfwd_channel_mutex);
+	for (i = 0; i < NUM_PERIPHERALS; i++)
+		mutex_init(&driver->diagfwd_channel_mutex[i]);
 	init_waitqueue_head(&driver->wait_q);
 	INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
 	INIT_WORK(&(driver->update_user_clients),
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index f9dc670d..cd49f00 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1303,6 +1303,8 @@
 
 static int diagfwd_mux_close(int id, int mode)
 {
+	uint8_t i;
+
 	switch (mode) {
 	case DIAG_USB_MODE:
 		driver->usb_connected = 0;
@@ -1323,10 +1325,23 @@
 		 */
 	} else {
 		/*
-		 * With clearing of masks on ODL exit and
-		 * USB disconnection, closing of the channel is
-		 * not needed.This enables read and drop of stale packets.
+		 * With sysfs parameter to clear masks set,
+		 * peripheral masks are cleared on ODL exit and
+		 * USB disconnection and buffers are not marked busy.
+		 * This enables read and drop of stale packets.
+		 *
+		 * With sysfs parameter to clear masks cleared,
+		 * masks are not cleared and buffers are to be marked
+		 * busy to ensure traffic generated by peripheral
+		 * are not read
 		 */
+		if (!(diag_mask_param())) {
+			for (i = 0; i < NUM_PERIPHERALS; i++) {
+				diagfwd_close(i, TYPE_DATA);
+				diagfwd_close(i, TYPE_CMD);
+			}
+		}
+		/* Re enable HDLC encoding */
 		pr_debug("diag: In %s, re-enabling HDLC encoding\n",
 		       __func__);
 		mutex_lock(&driver->hdlc_disable_mutex);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index b262897..e13871e 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -359,6 +359,8 @@
 		feature_mask_len = FEATURE_MASK_LEN;
 	}
 
+	diag_cmd_remove_reg_by_proc(peripheral);
+
 	driver->feature[peripheral].rcvd_feature_mask = 1;
 
 	for (i = 0; i < feature_mask_len && read_len < len; i++) {
@@ -660,7 +662,7 @@
 	if (!new_item)
 		return -ENOMEM;
 	kmemleak_not_leak(new_item);
-	new_item->process_name = kzalloc(strlen(process_name), GFP_KERNEL);
+	new_item->process_name = kzalloc(strlen(process_name) + 1, GFP_KERNEL);
 	if (!new_item->process_name) {
 		kfree(new_item);
 		new_item = NULL;
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 6685be3..5a8ef04 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -436,9 +436,9 @@
 			fwd_info->inited = 1;
 			fwd_info->read_bytes = 0;
 			fwd_info->write_bytes = 0;
-			spin_lock_init(&fwd_info->buf_lock);
-			spin_lock_init(&fwd_info->write_buf_lock);
+			mutex_init(&fwd_info->buf_mutex);
 			mutex_init(&fwd_info->data_mutex);
+			spin_lock_init(&fwd_info->write_buf_lock);
 		}
 	}
 
@@ -452,8 +452,8 @@
 			fwd_info->ch_open = 0;
 			fwd_info->read_bytes = 0;
 			fwd_info->write_bytes = 0;
-			spin_lock_init(&fwd_info->buf_lock);
 			spin_lock_init(&fwd_info->write_buf_lock);
+			mutex_init(&fwd_info->buf_mutex);
 			mutex_init(&fwd_info->data_mutex);
 			/*
 			 * This state shouldn't be set for Control channels
@@ -646,7 +646,7 @@
 
 	}
 
-	mutex_lock(&driver->diagfwd_channel_mutex);
+	mutex_lock(&driver->diagfwd_channel_mutex[peripheral]);
 	fwd_info = &early_init_info[transport][peripheral];
 	if (fwd_info->p_ops && fwd_info->p_ops->close)
 		fwd_info->p_ops->close(fwd_info->ctxt);
@@ -670,7 +670,7 @@
 		diagfwd_late_open(dest_info);
 	diagfwd_cntl_open(dest_info);
 	init_fn(peripheral);
-	mutex_unlock(&driver->diagfwd_channel_mutex);
+	mutex_unlock(&driver->diagfwd_channel_mutex[peripheral]);
 	diagfwd_queue_read(&peripheral_info[TYPE_DATA][peripheral]);
 	diagfwd_queue_read(&peripheral_info[TYPE_CMD][peripheral]);
 }
@@ -1065,7 +1065,6 @@
 
 void diagfwd_buffers_init(struct diagfwd_info *fwd_info)
 {
-	unsigned long flags;
 
 	if (!fwd_info)
 		return;
@@ -1076,10 +1075,10 @@
 		return;
 	}
 
-	spin_lock_irqsave(&fwd_info->buf_lock, flags);
+	mutex_lock(&fwd_info->buf_mutex);
 	if (!fwd_info->buf_1) {
 		fwd_info->buf_1 = kzalloc(sizeof(struct diagfwd_buf_t),
-					  GFP_ATOMIC);
+					  GFP_KERNEL);
 		if (!fwd_info->buf_1)
 			goto err;
 		kmemleak_not_leak(fwd_info->buf_1);
@@ -1087,7 +1086,7 @@
 	if (!fwd_info->buf_1->data) {
 		fwd_info->buf_1->data = kzalloc(PERIPHERAL_BUF_SZ +
 					APF_DIAG_PADDING,
-					GFP_ATOMIC);
+					GFP_KERNEL);
 		if (!fwd_info->buf_1->data)
 			goto err;
 		fwd_info->buf_1->len = PERIPHERAL_BUF_SZ;
@@ -1099,7 +1098,7 @@
 	if (fwd_info->type == TYPE_DATA) {
 		if (!fwd_info->buf_2) {
 			fwd_info->buf_2 = kzalloc(sizeof(struct diagfwd_buf_t),
-					      GFP_ATOMIC);
+					      GFP_KERNEL);
 			if (!fwd_info->buf_2)
 				goto err;
 			kmemleak_not_leak(fwd_info->buf_2);
@@ -1108,7 +1107,7 @@
 		if (!fwd_info->buf_2->data) {
 			fwd_info->buf_2->data = kzalloc(PERIPHERAL_BUF_SZ +
 							APF_DIAG_PADDING,
-						    GFP_ATOMIC);
+						    GFP_KERNEL);
 			if (!fwd_info->buf_2->data)
 				goto err;
 			fwd_info->buf_2->len = PERIPHERAL_BUF_SZ;
@@ -1124,7 +1123,7 @@
 				fwd_info->buf_1->data_raw =
 					kzalloc(PERIPHERAL_BUF_SZ +
 						APF_DIAG_PADDING,
-						GFP_ATOMIC);
+						GFP_KERNEL);
 				if (!fwd_info->buf_1->data_raw)
 					goto err;
 				fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ;
@@ -1134,7 +1133,7 @@
 				fwd_info->buf_2->data_raw =
 					kzalloc(PERIPHERAL_BUF_SZ +
 						APF_DIAG_PADDING,
-						GFP_ATOMIC);
+						GFP_KERNEL);
 				if (!fwd_info->buf_2->data_raw)
 					goto err;
 				fwd_info->buf_2->len_raw = PERIPHERAL_BUF_SZ;
@@ -1148,7 +1147,7 @@
 		if (!fwd_info->buf_1->data_raw) {
 			fwd_info->buf_1->data_raw = kzalloc(PERIPHERAL_BUF_SZ +
 						APF_DIAG_PADDING,
-							GFP_ATOMIC);
+							GFP_KERNEL);
 			if (!fwd_info->buf_1->data_raw)
 				goto err;
 			fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ;
@@ -1156,22 +1155,21 @@
 		}
 	}
 
-	spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+	mutex_unlock(&fwd_info->buf_mutex);
 	return;
 
 err:
-	spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+	mutex_unlock(&fwd_info->buf_mutex);
 	diagfwd_buffers_exit(fwd_info);
 }
 
 static void diagfwd_buffers_exit(struct diagfwd_info *fwd_info)
 {
-	unsigned long flags;
 
 	if (!fwd_info)
 		return;
 
-	spin_lock_irqsave(&fwd_info->buf_lock, flags);
+	mutex_lock(&fwd_info->buf_mutex);
 	if (fwd_info->buf_1) {
 		kfree(fwd_info->buf_1->data);
 		fwd_info->buf_1->data = NULL;
@@ -1188,7 +1186,7 @@
 		kfree(fwd_info->buf_2);
 		fwd_info->buf_2 = NULL;
 	}
-	spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+	mutex_unlock(&fwd_info->buf_mutex);
 }
 
 void diagfwd_write_buffers_init(struct diagfwd_info *fwd_info)
diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h
index b8deb38..5884a12 100644
--- a/drivers/char/diag/diagfwd_peripheral.h
+++ b/drivers/char/diag/diagfwd_peripheral.h
@@ -71,8 +71,8 @@
 	atomic_t opened;
 	unsigned long read_bytes;
 	unsigned long write_bytes;
-	spinlock_t buf_lock;
 	spinlock_t write_buf_lock;
+	struct mutex buf_mutex;
 	struct mutex data_mutex;
 	void *ctxt;
 	struct diagfwd_buf_t *buf_1;
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index 6403abc..af8bf00 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -34,14 +34,17 @@
 #include "diagfwd_socket.h"
 #include "diag_ipc_logging.h"
 
+#include <soc/qcom/subsystem_notif.h>
+#include <soc/qcom/subsystem_restart.h>
+
 #define DIAG_SVC_ID		0x1001
 
 #define MODEM_INST_BASE		0
 #define LPASS_INST_BASE		64
 #define WCNSS_INST_BASE		128
 #define SENSORS_INST_BASE	192
-#define WDSP_INST_BASE	256
-#define CDSP_INST_BASE  320
+#define CDSP_INST_BASE	256
+#define WDSP_INST_BASE  320
 
 #define INST_ID_CNTL		0
 #define INST_ID_CMD		1
@@ -50,6 +53,7 @@
 #define INST_ID_DCI		4
 
 struct diag_cntl_socket_info *cntl_socket;
+static uint64_t bootup_req[NUM_SOCKET_SUBSYSTEMS];
 
 struct diag_socket_info socket_data[NUM_PERIPHERALS] = {
 	{
@@ -287,13 +291,6 @@
 	spin_unlock_irqrestore(&info->lock, flags);
 	diag_ws_on_notify();
 
-	/*
-	 * Initialize read buffers for the servers. The servers must read data
-	 * first to get the address of its clients.
-	 */
-	if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER)
-		diagfwd_buffers_init(info->fwd_ctxt);
-
 	queue_work(info->wq, &(info->read_work));
 	wake_up_interruptible(&info->read_wait_q);
 }
@@ -422,7 +419,7 @@
 		return;
 	}
 	__socket_open_channel(info);
-	DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s exiting\n", info->name);
+	DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s opened client\n", info->name);
 }
 
 static void socket_open_server(struct diag_socket_info *info)
@@ -498,6 +495,13 @@
 	if (!atomic_read(&info->opened))
 		return;
 
+	if (bootup_req[info->peripheral] == PEPIPHERAL_SSR_UP) {
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: %s is up, stopping cleanup: bootup_req = %d\n",
+		info->name, (int)bootup_req[info->peripheral]);
+		return;
+	}
+
 	memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc));
 	diagfwd_channel_close(info->fwd_ctxt);
 
@@ -614,7 +618,9 @@
 	case CNTL_CMD_REMOVE_CLIENT:
 		DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s received remove client\n",
 			 info->name);
+		mutex_lock(&driver->diag_notifier_mutex);
 		socket_close_channel(info);
+		mutex_unlock(&driver->diag_notifier_mutex);
 		break;
 	default:
 		return -EINVAL;
@@ -623,6 +629,25 @@
 	return 0;
 }
 
+static int restart_notifier_cb(struct notifier_block *this,
+				  unsigned long code,
+				  void *data);
+
+struct restart_notifier_block {
+	unsigned int processor;
+	char *name;
+	struct notifier_block nb;
+};
+
+static struct restart_notifier_block restart_notifiers[] = {
+	{SOCKET_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
+	{SOCKET_ADSP, "adsp", .nb.notifier_call = restart_notifier_cb},
+	{SOCKET_WCNSS, "wcnss", .nb.notifier_call = restart_notifier_cb},
+	{SOCKET_SLPI, "slpi", .nb.notifier_call = restart_notifier_cb},
+	{SOCKET_CDSP, "cdsp", .nb.notifier_call = restart_notifier_cb},
+};
+
+
 static void cntl_socket_read_work_fn(struct work_struct *work)
 {
 	union cntl_port_msg msg;
@@ -630,7 +655,6 @@
 	struct kvec iov = { 0 };
 	struct msghdr read_msg = { 0 };
 
-
 	if (!cntl_socket)
 		return;
 
@@ -679,6 +703,9 @@
 	if (!info)
 		return;
 
+	if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER)
+		diagfwd_buffers_init(info->fwd_ctxt);
+
 	diagfwd_channel_read(info->fwd_ctxt);
 }
 
@@ -847,8 +874,11 @@
 int diag_socket_init(void)
 {
 	int err = 0;
+	int i;
 	int peripheral = 0;
+	void *handle;
 	struct diag_socket_info *info = NULL;
+	struct restart_notifier_block *nb;
 
 	for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
 		info = &socket_cntl[peripheral];
@@ -869,6 +899,17 @@
 		goto fail;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
+		nb = &restart_notifiers[i];
+		if (nb) {
+			handle = subsys_notif_register_notifier(nb->name,
+				&nb->nb);
+			DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+			"%s: registering notifier for '%s', handle=%p\n",
+			__func__, nb->name, handle);
+		}
+	}
+
 	register_ipcrtr_af_init_notifier(&socket_notify);
 fail:
 	return err;
@@ -904,6 +945,65 @@
 	return 0;
 }
 
+static int restart_notifier_cb(struct notifier_block *this, unsigned long code,
+	void *_cmd)
+{
+	struct restart_notifier_block *notifier;
+
+	notifier = container_of(this,
+			struct restart_notifier_block, nb);
+	if (!notifier) {
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: %s: invalid notifier block\n", __func__);
+		return NOTIFY_DONE;
+	}
+
+	mutex_lock(&driver->diag_notifier_mutex);
+	DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+	"%s: ssr for processor %d ('%s')\n",
+	__func__, notifier->processor, notifier->name);
+
+	switch (code) {
+
+	case SUBSYS_BEFORE_SHUTDOWN:
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: %s: SUBSYS_BEFORE_SHUTDOWN\n", __func__);
+		bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN;
+		break;
+
+	case SUBSYS_AFTER_SHUTDOWN:
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: %s: SUBSYS_AFTER_SHUTDOWN\n", __func__);
+		break;
+
+	case SUBSYS_BEFORE_POWERUP:
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: %s: SUBSYS_BEFORE_POWERUP\n", __func__);
+		break;
+
+	case SUBSYS_AFTER_POWERUP:
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: %s: SUBSYS_AFTER_POWERUP\n", __func__);
+		if (!bootup_req[notifier->processor]) {
+			bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN;
+			break;
+		}
+		bootup_req[notifier->processor] = PEPIPHERAL_SSR_UP;
+		break;
+
+	default:
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+		"diag: code: %lu\n", code);
+		break;
+	}
+	mutex_unlock(&driver->diag_notifier_mutex);
+	DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+	"diag: bootup_req[%s] = %d\n",
+	notifier->name, (int)bootup_req[notifier->processor]);
+
+	return NOTIFY_DONE;
+}
+
 int diag_socket_init_peripheral(uint8_t peripheral)
 {
 	struct diag_socket_info *info = NULL;
@@ -986,9 +1086,9 @@
 				      (info->data_ready > 0) || (!info->hdl) ||
 				      (atomic_read(&info->diag_state) == 0));
 	if (err) {
-		mutex_lock(&driver->diagfwd_channel_mutex);
+		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
 		diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-		mutex_unlock(&driver->diagfwd_channel_mutex);
+		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
 		return -ERESTARTSYS;
 	}
 
@@ -1000,9 +1100,9 @@
 		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
 			 "%s closing read thread. diag state is closed\n",
 			 info->name);
-		mutex_lock(&driver->diagfwd_channel_mutex);
+		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
 		diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-		mutex_unlock(&driver->diagfwd_channel_mutex);
+		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
 		return 0;
 	}
 
@@ -1069,10 +1169,10 @@
 	if (total_recd > 0) {
 		DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s read total bytes: %d\n",
 			 info->name, total_recd);
-		mutex_lock(&driver->diagfwd_channel_mutex);
+		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
 		err = diagfwd_channel_read_done(info->fwd_ctxt,
 						buf, total_recd);
-		mutex_unlock(&driver->diagfwd_channel_mutex);
+		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
 		if (err)
 			goto fail;
 	} else {
@@ -1085,9 +1185,9 @@
 	return 0;
 
 fail:
-	mutex_lock(&driver->diagfwd_channel_mutex);
+	mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
 	diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-	mutex_unlock(&driver->diagfwd_channel_mutex);
+	mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
 	return -EIO;
 }
 
diff --git a/drivers/char/diag/diagfwd_socket.h b/drivers/char/diag/diagfwd_socket.h
index a2b922a..a9487b1 100644
--- a/drivers/char/diag/diagfwd_socket.h
+++ b/drivers/char/diag/diagfwd_socket.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, 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
@@ -24,10 +24,24 @@
 #define PORT_TYPE_SERVER		0
 #define PORT_TYPE_CLIENT		1
 
+#define PEPIPHERAL_AFTER_BOOT		0
+#define PEPIPHERAL_SSR_DOWN		1
+#define PEPIPHERAL_SSR_UP		2
+
 #define CNTL_CMD_NEW_SERVER		4
 #define CNTL_CMD_REMOVE_SERVER		5
 #define CNTL_CMD_REMOVE_CLIENT		6
 
+enum {
+	SOCKET_MODEM,
+	SOCKET_ADSP,
+	SOCKET_WCNSS,
+	SOCKET_SLPI,
+	SOCKET_CDSP,
+	SOCKET_APPS,
+	NUM_SOCKET_SUBSYSTEMS,
+};
+
 struct diag_socket_info {
 	uint8_t peripheral;
 	uint8_t type;
diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c
index a4a1cfb..cd4fdfb 100644
--- a/drivers/devfreq/bimc-bwmon.c
+++ b/drivers/devfreq/bimc-bwmon.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -65,7 +65,7 @@
 	void __iomem *base;
 	void __iomem *global_base;
 	unsigned int mport;
-	unsigned int irq;
+	int irq;
 	const struct bwmon_spec *spec;
 	struct device *dev;
 	struct bw_hwmon hw;
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 6e793d9..6c2d643 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -78,7 +78,8 @@
 	.get_brightness = sde_backlight_device_get_brightness,
 };
 
-static int sde_backlight_setup(struct sde_connector *c_conn)
+static int sde_backlight_setup(struct sde_connector *c_conn,
+					struct drm_device *dev)
 {
 	struct backlight_device *bl_device;
 	struct backlight_properties props;
@@ -87,7 +88,7 @@
 	static int display_count;
 	char bl_node_name[BL_NODE_NAME_SIZE];
 
-	if (!c_conn) {
+	if (!c_conn || !dev || !dev->dev) {
 		SDE_ERROR("invalid param\n");
 		return -EINVAL;
 	} else if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) {
@@ -104,7 +105,7 @@
 	props.brightness = bl_config->brightness_max_level;
 	snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight",
 							display_count);
-	bl_device = backlight_device_register(bl_node_name, c_conn->base.kdev,
+	bl_device = backlight_device_register(bl_node_name, dev->dev,
 			c_conn, &sde_backlight_device_ops, &props);
 	if (IS_ERR_OR_NULL(bl_device)) {
 		SDE_ERROR("Failed to register backlight: %ld\n",
@@ -779,7 +780,7 @@
 		goto error_cleanup_fence;
 	}
 
-	rc = sde_backlight_setup(c_conn);
+	rc = sde_backlight_setup(c_conn, dev);
 	if (rc) {
 		SDE_ERROR("failed to setup backlight, rc=%d\n", rc);
 		goto error_cleanup_fence;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 98c59c3..2393e61 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -348,9 +348,16 @@
 static void sde_kms_prepare_commit(struct msm_kms *kms,
 		struct drm_atomic_state *state)
 {
-	struct sde_kms *sde_kms = to_sde_kms(kms);
-	struct drm_device *dev = sde_kms->dev;
-	struct msm_drm_private *priv = dev->dev_private;
+	struct sde_kms *sde_kms;
+	struct msm_drm_private *priv;
+
+	if (!kms)
+		return;
+	sde_kms = to_sde_kms(kms);
+
+	if (!sde_kms->dev || !sde_kms->dev->dev_private)
+		return;
+	priv = sde_kms->dev->dev_private;
 
 	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
 }
@@ -373,13 +380,20 @@
 static void sde_kms_complete_commit(struct msm_kms *kms,
 		struct drm_atomic_state *old_state)
 {
-	struct sde_kms *sde_kms = to_sde_kms(kms);
-	struct drm_device *dev = sde_kms->dev;
-	struct msm_drm_private *priv = dev->dev_private;
+	struct sde_kms *sde_kms;
+	struct msm_drm_private *priv;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *old_crtc_state;
 	int i;
 
+	if (!kms || !old_state)
+		return;
+	sde_kms = to_sde_kms(kms);
+
+	if (!sde_kms->dev || !sde_kms->dev->dev_private)
+		return;
+	priv = sde_kms->dev->dev_private;
+
 	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i)
 		sde_crtc_complete_commit(crtc, old_crtc_state);
 	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
@@ -1515,7 +1529,7 @@
 	}
 
 	rc = sde_core_perf_init(&sde_kms->perf, dev, sde_kms->catalog,
-			&priv->phandle, priv->pclient, "core_clk_src");
+			&priv->phandle, priv->pclient, "core_clk");
 	if (rc) {
 		SDE_ERROR("failed to init perf %d\n", rc);
 		goto perf_err;
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index fddfb2c..28d93a9 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -718,9 +718,9 @@
 #define A6XX_GMU_GENERAL_7			0x1F9CC
 
 #define A6XX_GMU_AO_INTERRUPT_EN		0x23B03
-#define A6XX_GMU_HOST_INTERRUPT_CLR		0x23B04
-#define A6XX_GMU_HOST_INTERRUPT_STATUS		0x23B05
-#define A6XX_GMU_HOST_INTERRUPT_MASK		0x23B06
+#define A6XX_GMU_AO_HOST_INTERRUPT_CLR		0x23B04
+#define A6XX_GMU_AO_HOST_INTERRUPT_STATUS	0x23B05
+#define A6XX_GMU_AO_HOST_INTERRUPT_MASK		0x23B06
 #define A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS	0x23B0C
 #define A6XX_GMU_AHB_FENCE_STATUS		0x23B13
 #define A6XX_GMU_RBBM_INT_UNMASKED_STATUS	0x23B15
@@ -764,7 +764,6 @@
 #define PDC_GPU_TCS1_CMD0_MSGID			0x21575
 #define PDC_GPU_TCS1_CMD0_ADDR			0x21576
 #define PDC_GPU_TCS1_CMD0_DATA			0x21577
-#define PDC_GPU_TIMESTAMP_UNIT1_EN_DRV0		0x23489
 #define PDC_GPU_SEQ_MEM_0			0xA0000
 
 #endif /* _A6XX_REG_H */
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 75d5587..530529f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -618,9 +618,9 @@
 	ADRENO_REG_VBIF_XIN_HALT_CTRL1,
 	ADRENO_REG_VBIF_VERSION,
 	ADRENO_REG_GMU_AO_INTERRUPT_EN,
-	ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
-	ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
-	ADRENO_REG_GMU_HOST_INTERRUPT_MASK,
+	ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+	ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS,
+	ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
 	ADRENO_REG_GMU_PWR_COL_KEEPALIVE,
 	ADRENO_REG_GMU_AHB_FENCE_STATUS,
 	ADRENO_REG_GMU_RPMH_POWER_STATE,
@@ -629,6 +629,7 @@
 	ADRENO_REG_GMU_HFI_SFR_ADDR,
 	ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
 	ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
+	ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
 	ADRENO_REG_GMU_HOST2GMU_INTR_SET,
 	ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
 	ADRENO_REG_GMU_HOST2GMU_INTR_RAW_INFO,
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 944faa3..6609357 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -504,15 +504,6 @@
 	__raw_writel(value, reg);
 }
 
-static void _gmu_regrmw(struct kgsl_device *device,
-		unsigned int offsetwords, unsigned int mask)
-{
-	unsigned int value;
-
-	kgsl_gmu_regread(device, offsetwords, &value);
-	kgsl_gmu_regwrite(device, offsetwords, value | mask);
-}
-
 /*
  * _load_gmu_rpmh_ucode() - Load the ucode into the GPU PDC/RSC blocks
  * PDC and RSC execute GPU power on/off RPMh sequence
@@ -651,22 +642,25 @@
 	/* Configure registers for idle setting. The setting is cumulative */
 	switch (gmu->idle_level) {
 	case GPU_HW_MIN_VOLT:
-		_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, MIN_BW_ENABLE_MASK);
-		_gmu_regrmw(device, A6XX_GMU_RPMH_HYST_CTRL, MIN_BW_HYST);
+		kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, 0,
+				MIN_BW_ENABLE_MASK);
+		kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_HYST_CTRL, 0,
+				MIN_BW_HYST);
 		/* fall through */
 	case GPU_HW_NAP:
-		_gmu_regrmw(device, A6XX_GMU_GPU_NAP_CTRL, HW_NAP_ENABLE_MASK);
+		kgsl_gmu_regrmw(device, A6XX_GMU_GPU_NAP_CTRL, 0,
+				HW_NAP_ENABLE_MASK);
 		/* fall through */
 	case GPU_HW_IFPC:
 		kgsl_gmu_regwrite(device, A6XX_GMU_PWR_COL_INTER_FRAME_HYST,
 				0x000A0080);
-		_gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL,
+		kgsl_gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0,
 				IFPC_ENABLE_MASK);
 		/* fall through */
 	case GPU_HW_SPTP_PC:
 		kgsl_gmu_regwrite(device, A6XX_GMU_PWR_COL_SPTPRAC_HYST,
 				0x000A0080);
-		_gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL,
+		kgsl_gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0,
 				SPTP_ENABLE_MASK);
 		/* fall through */
 	default:
@@ -675,11 +669,13 @@
 
 	/* ACD feature enablement */
 	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM))
-		_gmu_regrmw(device, A6XX_GMU_BOOT_KMD_LM_HANDSHAKE, BIT(10));
+		kgsl_gmu_regrmw(device, A6XX_GMU_BOOT_KMD_LM_HANDSHAKE, 0,
+				BIT(10));
 
 	/* Enable RPMh GPU client */
 	if (ADRENO_FEATURE(adreno_dev, ADRENO_RPMH))
-		_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, RPMH_ENABLE_MASK);
+		kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, 0,
+				RPMH_ENABLE_MASK);
 
 	/* Disable reference bandgap voltage */
 	kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 1);
@@ -721,9 +717,8 @@
 {
 	struct gmu_device *gmu = &device->gmu;
 
-	kgsl_gmu_regwrite(device, A6XX_GMU_GMU2HOST_INTR_MASK,
-			(HFI_IRQ_MASK & (~HFI_IRQ_MSGQ_MASK)));
-
+	kgsl_gmu_regrmw(device, A6XX_GMU_GMU2HOST_INTR_MASK,
+			HFI_IRQ_MSGQ_MASK, 0);
 	kgsl_gmu_regwrite(device, A6XX_GMU_HFI_CTRL_INIT, 1);
 
 	if (timed_poll_check(device,
@@ -1092,7 +1087,7 @@
 	ret = a6xx_hm_sptprac_control(device, false);
 
 	/* RSC sleep sequence */
-	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TIMESTAMP_UNIT1_EN_DRV0, 1);
+	kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
 	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 1);
 	wmb();
 
@@ -2053,12 +2048,12 @@
 				A6XX_GMU_ALWAYS_ON_COUNTER_H),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_INTERRUPT_EN,
 				A6XX_GMU_AO_INTERRUPT_EN),
-	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
-				A6XX_GMU_HOST_INTERRUPT_CLR),
-	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
-				A6XX_GMU_HOST_INTERRUPT_STATUS),
-	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_MASK,
-				A6XX_GMU_HOST_INTERRUPT_MASK),
+	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+				A6XX_GMU_AO_HOST_INTERRUPT_CLR),
+	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS,
+				A6XX_GMU_AO_HOST_INTERRUPT_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
+				A6XX_GMU_AO_HOST_INTERRUPT_MASK),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_PWR_COL_KEEPALIVE,
 				A6XX_GMU_GMU_PWR_COL_KEEPALIVE),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AHB_FENCE_STATUS,
@@ -2075,6 +2070,8 @@
 				A6XX_GMU_GMU2HOST_INTR_CLR),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
 				A6XX_GMU_GMU2HOST_INTR_INFO),
+	ADRENO_REG_DEFINE(ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+				A6XX_GMU_GMU2HOST_INTR_MASK),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_SET,
 				A6XX_GMU_HOST2GMU_INTR_SET),
 	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 15157b76..9259e71 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -221,12 +221,12 @@
 
 static const unsigned int a6xx_registers[] = {
 	/* RBBM */
-	0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0014, 0x0014,
-	0x0018, 0x001B, 0x001e, 0x0032, 0x0038, 0x003C, 0x0042, 0x0042,
-	0x0044, 0x0044, 0x0047, 0x0047, 0x0056, 0x0056, 0x00AD, 0x00AE,
-	0x00B0, 0x00FB, 0x0100, 0x011D, 0x0200, 0x020D, 0x0210, 0x0213,
-	0x0218, 0x023D, 0x0400, 0x04F9, 0x0500, 0x0500, 0x0505, 0x050B,
-	0x050E, 0x0511, 0x0533, 0x0533, 0x0540, 0x0555,
+	0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0018, 0x001B,
+	0x001e, 0x0032, 0x0038, 0x003C, 0x0042, 0x0042, 0x0044, 0x0044,
+	0x0047, 0x0047, 0x0056, 0x0056, 0x00AD, 0x00AE, 0x00B0, 0x00FB,
+	0x0100, 0x011D, 0x0200, 0x020D, 0x0210, 0x0213, 0x0218, 0x023D,
+	0x0400, 0x04F9, 0x0500, 0x0500, 0x0505, 0x050B, 0x050E, 0x0511,
+	0x0533, 0x0533, 0x0540, 0x0555,
 	/* CP */
 	0x0800, 0x0808, 0x0810, 0x0813, 0x0820, 0x0821, 0x0823, 0x0827,
 	0x0830, 0x0833, 0x0840, 0x0843, 0x084F, 0x086F, 0x0880, 0x088A,
@@ -240,8 +240,8 @@
 	0x0E10, 0x0E13, 0x0E17, 0x0E19, 0x0E1C, 0x0E2B, 0x0E30, 0x0E32,
 	0x0E38, 0x0E39,
 	/* GRAS */
-	0x8600, 0x8601, 0x8604, 0x8605, 0x8610, 0x861B, 0x8620, 0x8620,
-	0x8628, 0x862B, 0x8630, 0x8637,
+	0x8600, 0x8601, 0x8610, 0x861B, 0x8620, 0x8620, 0x8628, 0x862B,
+	0x8630, 0x8637,
 	/* RB */
 	0x8E01, 0x8E01, 0x8E04, 0x8E05, 0x8E07, 0x8E08, 0x8E0C, 0x8E0C,
 	0x8E10, 0x8E1C, 0x8E20, 0x8E25, 0x8E28, 0x8E28, 0x8E2C, 0x8E2F,
@@ -254,7 +254,7 @@
 	0x9E70, 0x9E72, 0x9E78, 0x9E79, 0x9E80, 0x9FFF,
 	/* VFD */
 	0xA600, 0xA601, 0xA603, 0xA603, 0xA60A, 0xA60A, 0xA610, 0xA617,
-	0xA630, 0xA630, 0xD200, 0xD263,
+	0xA630, 0xA630,
 };
 
 enum a6xx_debugbus_id {
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index bf31c00..d955aa0 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -569,6 +569,17 @@
 	device->ftbl->regwrite(device, offsetwords, val | bits);
 }
 
+static inline void kgsl_gmu_regrmw(struct kgsl_device *device,
+		unsigned int offsetwords,
+		unsigned int mask, unsigned int bits)
+{
+	unsigned int val = 0;
+
+	kgsl_gmu_regread(device, offsetwords, &val);
+	val &= ~mask;
+	kgsl_gmu_regwrite(device, offsetwords, val | bits);
+}
+
 static inline int kgsl_idle(struct kgsl_device *device)
 {
 	return device->ftbl->idle(device);
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 17c10eb..416085f 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -748,44 +748,49 @@
 {
 	struct gmu_device *gmu = data;
 	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
-	struct kgsl_hfi *hfi = &gmu->hfi;
 	unsigned int status = 0;
 
-	if (irq == gmu->gmu_interrupt_num) {
-		adreno_read_gmureg(ADRENO_DEVICE(device),
-				ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
-				&status);
+	adreno_read_gmureg(ADRENO_DEVICE(device),
+			ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS, &status);
+	adreno_write_gmureg(ADRENO_DEVICE(device),
+			ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, status);
 
-		/* Ignore GMU_INT_RSCC_COMP interrupts */
-		if (status & GMU_INT_WDOG_BITE)
-			dev_err_ratelimited(&gmu->pdev->dev,
-					"GMU watchdog expired interrupt\n");
-		if (status & GMU_INT_DBD_WAKEUP)
-			dev_err_ratelimited(&gmu->pdev->dev,
-					"GMU doorbell interrupt received\n");
-		if (status & GMU_INT_HOST_AHB_BUS_ERR)
-			dev_err_ratelimited(&gmu->pdev->dev,
-					"AHB bus error interrupt received\n");
+	/* Ignore GMU_INT_RSCC_COMP and GMU_INT_DBD WAKEUP interrupts */
+	if (status & GMU_INT_WDOG_BITE)
+		dev_err_ratelimited(&gmu->pdev->dev,
+				"GMU watchdog expired interrupt received\n");
+	if (status & GMU_INT_HOST_AHB_BUS_ERR)
+		dev_err_ratelimited(&gmu->pdev->dev,
+				"AHB bus error interrupt received\n");
+	if (status & ~GMU_AO_INT_MASK)
+		dev_err_ratelimited(&gmu->pdev->dev,
+				"Unhandled GMU interrupts 0x%lx\n",
+				status & ~GMU_AO_INT_MASK);
 
-		adreno_write_gmureg(ADRENO_DEVICE(device),
-				ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
-				status);
-	} else {
-		adreno_read_gmureg(ADRENO_DEVICE(device),
-				ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
-				&status);
-		adreno_write_gmureg(ADRENO_DEVICE(device),
-				ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
-				status);
+	return IRQ_HANDLED;
+}
 
-		if (status & HFI_IRQ_MASK) {
-			if (status & HFI_IRQ_MSGQ_MASK)
-				tasklet_hi_schedule(&hfi->tasklet);
-		} else
-			dev_err_ratelimited(&gmu->pdev->dev,
-					"Unhandled GMU interrupts %x\n",
-					status);
-	}
+static irqreturn_t hfi_irq_handler(int irq, void *data)
+{
+	struct kgsl_hfi *hfi = data;
+	struct gmu_device *gmu = container_of(hfi, struct gmu_device, hfi);
+	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
+	unsigned int status = 0;
+
+	adreno_read_gmureg(ADRENO_DEVICE(device),
+			ADRENO_REG_GMU_GMU2HOST_INTR_INFO, &status);
+	adreno_write_gmureg(ADRENO_DEVICE(device),
+			ADRENO_REG_GMU_GMU2HOST_INTR_CLR, status);
+
+	if (status & HFI_IRQ_MSGQ_MASK)
+		tasklet_hi_schedule(&hfi->tasklet);
+	if (status & HFI_IRQ_CM3_FAULT_MASK)
+		dev_err_ratelimited(&gmu->pdev->dev,
+				"GMU CM3 fault interrupt received\n");
+	if (status & ~HFI_IRQ_MASK)
+		dev_err_ratelimited(&gmu->pdev->dev,
+				"Unhandled HFI interrupts 0x%lx\n",
+				status & ~HFI_IRQ_MASK);
 
 	return IRQ_HANDLED;
 }
@@ -978,6 +983,82 @@
 	return 0;
 }
 
+static int gmu_irq_probe(struct gmu_device *gmu)
+{
+	int ret;
+	struct kgsl_hfi *hfi = &gmu->hfi;
+
+	hfi->hfi_interrupt_num = platform_get_irq_byname(gmu->pdev,
+			"kgsl_hfi_irq");
+	ret = devm_request_irq(&gmu->pdev->dev,
+			hfi->hfi_interrupt_num,
+			hfi_irq_handler, IRQF_TRIGGER_HIGH,
+			"HFI", hfi);
+	if (ret) {
+		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
+				hfi->hfi_interrupt_num, ret);
+		return ret;
+	}
+
+	gmu->gmu_interrupt_num = platform_get_irq_byname(gmu->pdev,
+			"kgsl_gmu_irq");
+	ret = devm_request_irq(&gmu->pdev->dev,
+			gmu->gmu_interrupt_num,
+			gmu_irq_handler, IRQF_TRIGGER_HIGH,
+			"GMU", gmu);
+	if (ret)
+		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
+				gmu->gmu_interrupt_num, ret);
+
+	return ret;
+}
+
+static void gmu_irq_enable(struct kgsl_device *device)
+{
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct gmu_device *gmu = &device->gmu;
+	struct kgsl_hfi *hfi = &gmu->hfi;
+
+	/* Clear any pending IRQs before unmasking on GMU */
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
+			0xFFFFFFFF);
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+			0xFFFFFFFF);
+
+	/* Unmask needed IRQs on GMU */
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+			(unsigned int) ~HFI_IRQ_MASK);
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
+			(unsigned int) ~GMU_AO_INT_MASK);
+
+	/* Enable all IRQs on host */
+	enable_irq(hfi->hfi_interrupt_num);
+	enable_irq(gmu->gmu_interrupt_num);
+}
+
+static void gmu_irq_disable(struct kgsl_device *device)
+{
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct gmu_device *gmu = &device->gmu;
+	struct kgsl_hfi *hfi = &gmu->hfi;
+
+	/* Disable all IRQs on host */
+	disable_irq(gmu->gmu_interrupt_num);
+	disable_irq(hfi->hfi_interrupt_num);
+
+	/* Mask all IRQs on GMU */
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
+			0xFFFFFFFF);
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+			0xFFFFFFFF);
+
+	/* Clear any pending IRQs before disabling */
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+			0xFFFFFFFF);
+	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
+			0xFFFFFFFF);
+}
+
 /* Do not access any GMU registers in GMU probe function */
 int gmu_probe(struct kgsl_device *device)
 {
@@ -1024,32 +1105,13 @@
 
 	gmu->gmu2gpu_offset = (gmu->reg_phys - device->reg_phys) >> 2;
 
-	/* Initialize HFI GMU interrupts */
-	hfi->hfi_interrupt_num = platform_get_irq_byname(gmu->pdev,
-						"kgsl_hfi_irq");
-	ret = devm_request_irq(&gmu->pdev->dev,
-				  hfi->hfi_interrupt_num,
-				  gmu_irq_handler, IRQF_TRIGGER_HIGH,
-				  "GMU", gmu);
-	if (ret) {
-		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
-			      hfi->hfi_interrupt_num, ret);
+	/* Initialize HFI and GMU interrupts */
+	ret = gmu_irq_probe(gmu);
+	if (ret)
 		goto error;
-	}
-
-	gmu->gmu_interrupt_num = platform_get_irq_byname(gmu->pdev,
-						"kgsl_gmu_irq");
-	ret = devm_request_irq(&gmu->pdev->dev,
-				  gmu->gmu_interrupt_num,
-				  gmu_irq_handler, IRQF_TRIGGER_HIGH,
-				  "GMU", gmu);
-	if (ret) {
-		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
-			      gmu->gmu_interrupt_num, ret);
-		goto error;
-	}
 
 	/* Don't enable GMU interrupts until GMU started */
+	/* We cannot use gmu_irq_disable because it writes registers */
 	disable_irq(gmu->gmu_interrupt_num);
 	disable_irq(hfi->hfi_interrupt_num);
 
@@ -1199,7 +1261,6 @@
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	struct gmu_device *gmu = &device->gmu;
-	struct kgsl_hfi *hfi = &gmu->hfi;
 	int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;
 
 	if (!kgsl_gmu_isenabled(device))
@@ -1234,8 +1295,7 @@
 		if (ret)
 			goto error_bus;
 
-		enable_irq(hfi->hfi_interrupt_num);
-		enable_irq(gmu->gmu_interrupt_num);
+		gmu_irq_enable(device);
 
 		ret = hfi_start(gmu, GMU_COLD_BOOT);
 		if (ret)
@@ -1253,8 +1313,7 @@
 		if (ret)
 			goto error_clks;
 
-		enable_irq(hfi->hfi_interrupt_num);
-		enable_irq(gmu->gmu_interrupt_num);
+		gmu_irq_enable(device);
 
 		ret = hfi_start(gmu, GMU_WARM_BOOT);
 		if (ret)
@@ -1292,8 +1351,7 @@
 
 error_gpu:
 	hfi_stop(gmu);
-	disable_irq(gmu->gmu_interrupt_num);
-	disable_irq(hfi->hfi_interrupt_num);
+	gmu_irq_disable(device);
 	if (device->state == KGSL_STATE_INIT ||
 			device->state == KGSL_STATE_SUSPEND) {
 		if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
@@ -1315,7 +1373,6 @@
 void gmu_stop(struct kgsl_device *device)
 {
 	struct gmu_device *gmu = &device->gmu;
-	struct kgsl_hfi *hfi = &gmu->hfi;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 
@@ -1333,9 +1390,7 @@
 	/* Pending message in all queues are abandoned */
 	hfi_stop(gmu);
 	clear_bit(GMU_HFI_ON, &gmu->flags);
-
-	disable_irq(gmu->gmu_interrupt_num);
-	disable_irq(hfi->hfi_interrupt_num);
+	gmu_irq_disable(device);
 
 	gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
 	gmu_disable_clks(gmu);
@@ -1358,6 +1413,7 @@
 	tasklet_kill(&hfi->tasklet);
 
 	gmu_stop(device);
+	gmu_irq_disable(device);
 
 	while ((i < MAX_GMU_CLKS) && gmu->clks[i]) {
 		gmu->clks[i] = NULL;
@@ -1365,14 +1421,12 @@
 	}
 
 	if (gmu->gmu_interrupt_num) {
-		disable_irq(gmu->gmu_interrupt_num);
 		devm_free_irq(&gmu->pdev->dev,
 				gmu->gmu_interrupt_num, gmu);
 		gmu->gmu_interrupt_num = 0;
 	}
 
 	if (hfi->hfi_interrupt_num) {
-		disable_irq(hfi->hfi_interrupt_num);
 		devm_free_irq(&gmu->pdev->dev,
 				hfi->hfi_interrupt_num, gmu);
 		hfi->hfi_interrupt_num = 0;
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index ac2c151..a2ca67c 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -26,7 +26,6 @@
 #define GMU_INT_HOST_AHB_BUS_ERR	BIT(5)
 #define GMU_AO_INT_MASK		\
 		(GMU_INT_WDOG_BITE |	\
-		GMU_INT_DBD_WAKEUP |	\
 		GMU_INT_HOST_AHB_BUS_ERR)
 
 #define MAX_GMUFW_SIZE	0x2000	/* in dwords */
diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h
index 39b513e..83abec4 100644
--- a/drivers/gpu/msm/kgsl_hfi.h
+++ b/drivers/gpu/msm/kgsl_hfi.h
@@ -38,16 +38,15 @@
 #define GMU_QUEUE_START_ADDR(hfi_mem, i) \
 	((hfi_mem)->gmuaddr + HFI_QUEUE_OFFSET(i))
 
-#define HFI_IRQ_MSGQ_MASK		0x1
-#define HFI_IRQ_DBGQ_MASK		0x2
-#define HFI_IRQ_BLOCKED_MSG_MASK	0x4
-#define HFI_IRQ_GMU_ERR_MASK		0xFF0000
-#define HFI_IRQ_OOB_MASK		0xFF000000
-#define HFI_IRQ_MASK  (HFI_IRQ_MSGQ_MASK |\
-			HFI_IRQ_DBGQ_MASK |\
-			HFI_IRQ_BLOCKED_MSG_MASK |\
-			HFI_IRQ_GMU_ERR_MASK |\
-			HFI_IRQ_OOB_MASK)
+#define HFI_IRQ_MSGQ_MASK		BIT(0)
+#define HFI_IRQ_DBGQ_MASK		BIT(1)
+#define HFI_IRQ_BLOCKED_MSG_MASK	BIT(2)
+#define HFI_IRQ_CM3_FAULT_MASK		BIT(23)
+#define HFI_IRQ_GMU_ERR_MASK		GENMASK(22, 16)
+#define HFI_IRQ_OOB_MASK		GENMASK(31, 24)
+#define HFI_IRQ_MASK			(HFI_IRQ_MSGQ_MASK |\
+					HFI_IRQ_CM3_FAULT_MASK)
+
 /**
  * struct hfi_queue_table_header - HFI queue table structure
  * @version: HFI protocol version
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index 0af9387..4672233 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -1541,6 +1541,9 @@
 			memcpy(mux_channel[rmnet_index].vchannel_name,
 				extend_ioctl_data.u.rmnet_mux_val.vchannel_name,
 				sizeof(mux_channel[rmnet_index].vchannel_name));
+			mux_channel[rmnet_index].vchannel_name[
+				IFNAMSIZ - 1] = '\0';
+
 			IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n",
 				mux_channel[rmnet_index].vchannel_name,
 				mux_channel[rmnet_index].mux_id,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index cf99e64..a7dbfc6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -5528,13 +5528,6 @@
 		return result;
 	}
 
-	result = of_platform_populate(pdev_p->dev.of_node,
-		pdrv_match, NULL, &pdev_p->dev);
-	if (result) {
-		IPAERR("failed to populate platform\n");
-		return result;
-	}
-
 	if (of_property_read_bool(pdev_p->dev.of_node, "qcom,arm-smmu")) {
 		if (of_property_read_bool(pdev_p->dev.of_node,
 		    "qcom,smmu-s1-bypass"))
@@ -5580,6 +5573,13 @@
 		}
 	}
 
+	result = of_platform_populate(pdev_p->dev.of_node,
+		pdrv_match, NULL, &pdev_p->dev);
+	if (result) {
+		IPAERR("failed to populate platform\n");
+		return result;
+	}
+
 	return result;
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index cb25b09..56e7718 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1655,6 +1655,9 @@
 				extend_ioctl_data.u.rmnet_mux_val.vchannel_name,
 				sizeof(mux_channel[rmnet_index]
 					.vchannel_name));
+			mux_channel[rmnet_index].vchannel_name[
+				IFNAMSIZ - 1] = '\0';
+
 			IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n",
 				mux_channel[rmnet_index].vchannel_name,
 				mux_channel[rmnet_index].mux_id,
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index 72fc3a4..91d6349 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -311,7 +311,12 @@
 		if (list_empty(&cur_bcm_clist[i]))
 			continue;
 		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
-			if (cur_bcm->updated) {
+			if (cur_bcm->updated ||
+				(cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
+				cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
+				cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
+				cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0 &&
+				init_time == true)) {
 				if (last_tcs != -1 &&
 					list_is_last(&cur_bcm->link,
 						&cur_bcm_clist[i])) {
@@ -356,18 +361,19 @@
 				if (last_tcs != -1 &&
 					list_is_last(&cur_bcm->link,
 					&cur_bcm_clist[i])) {
-					cmdlist_wake[k].data |=
+					cmdlist_wake[last_tcs].data |=
 						BCM_TCS_CMD_COMMIT_MASK;
-					cmdlist_sleep[k].data |=
+					cmdlist_sleep[last_tcs].data |=
 						BCM_TCS_CMD_COMMIT_MASK;
-					cmdlist_wake[k].complete = true;
-					cmdlist_sleep[k].complete = true;
+					cmdlist_wake[last_tcs].complete = true;
+					cmdlist_sleep[last_tcs].complete = true;
 					idx++;
 				}
 				continue;
 			}
 			last_tcs = k;
 			n_sleep[idx]++;
+			n_wake[idx]++;
 			if (list_is_last(&cur_bcm->link,
 						&cur_bcm_clist[i])) {
 				commit = true;
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 2faed7f..acbd26b 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -52,7 +52,7 @@
 obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
 obj-$(CONFIG_INTEL_PCH_THERMAL)	+= intel_pch_thermal.o
 obj-$(CONFIG_ST_THERMAL)	+= st/
-obj-$(CONFIG_QCOM_TSENS)	+= qcom/
+obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra/
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index a6245d5..37125c0 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -548,11 +548,29 @@
 	if (cpufreq_device->cpufreq_floor_state == state)
 		return 0;
 
-	floor_freq = cpufreq_device->freq_table[state];
 	cpufreq_device->cpufreq_floor_state = state;
-	cpufreq_device->floor_freq = floor_freq;
 
-	cpufreq_update_policy(cpu);
+	/*
+	 * Check if the device has a platform mitigation function that
+	 * can handle the CPU freq mitigation, if not, notify cpufreq
+	 * framework.
+	 */
+	if (cpufreq_device->plat_ops &&
+		cpufreq_device->plat_ops->floor_limit) {
+		/*
+		 * Last level is core isolation so use the frequency
+		 * of previous state.
+		 */
+		if (state == cpufreq_device->max_level)
+			state--;
+		floor_freq = cpufreq_device->freq_table[state];
+		cpufreq_device->floor_freq = floor_freq;
+		cpufreq_device->plat_ops->floor_limit(cpu, floor_freq);
+	} else {
+		floor_freq = cpufreq_device->freq_table[state];
+		cpufreq_device->floor_freq = floor_freq;
+		cpufreq_update_policy(cpu);
+	}
 
 	return 0;
 }
diff --git a/drivers/thermal/qcom/bcl_peripheral.c b/drivers/thermal/qcom/bcl_peripheral.c
index 55ff770..75e553f 100644
--- a/drivers/thermal/qcom/bcl_peripheral.c
+++ b/drivers/thermal/qcom/bcl_peripheral.c
@@ -259,7 +259,7 @@
 		 */
 		for (vbat_idx = 2; vbat_idx < BCL_STD_VBAT_NR;
 			vbat_idx++) {
-			if (vbat_uv > vbat_low[vbat_idx])
+			if (vbat_uv >= vbat_low[vbat_idx])
 				continue;
 			break;
 		}
@@ -274,7 +274,7 @@
 		 */
 		for (vbat_idx = 1; vbat_idx < (BCL_STD_VBAT_NR - 1);
 			vbat_idx++) {
-			if (vbat_uv > vbat_low[vbat_idx])
+			if (vbat_uv >= vbat_low[vbat_idx])
 				continue;
 			break;
 		}
diff --git a/drivers/thermal/qcom/msm_lmh_dcvs.c b/drivers/thermal/qcom/msm_lmh_dcvs.c
index 7b6952f..74f5ce0 100644
--- a/drivers/thermal/qcom/msm_lmh_dcvs.c
+++ b/drivers/thermal/qcom/msm_lmh_dcvs.c
@@ -396,8 +396,6 @@
 			continue;
 		lmh_node = of_parse_phandle(cpu_node, "qcom,lmh-dcvs", 0);
 		if (lmh_node == dn) {
-			affinity = MPIDR_AFFINITY_LEVEL(
-					cpu_logical_map(cpu), 1);
 			/*set the cpumask*/
 			cpumask_set_cpu(cpu, &(mask));
 		}
@@ -409,7 +407,7 @@
 	 * We return error if none of the CPUs have
 	 * reference to our LMH node
 	 */
-	if (affinity == -1)
+	if (cpumask_empty(&mask))
 		return -EINVAL;
 
 	ret = limits_dcvs_get_freq_limits(cpumask_first(&mask), &max_freq,
@@ -426,6 +424,9 @@
 		return -ENOMEM;
 
 	cpumask_copy(&hw->core_map, &mask);
+	ret = of_property_read_u32(dn, "qcom,affinity", &affinity);
+	if (ret)
+		return -ENODEV;
 	switch (affinity) {
 	case 0:
 		hw->affinity = LIMITS_CLUSTER_0;
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index b3cb5c0..df9be34 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -27,6 +27,8 @@
 #include <linux/serial_core.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/msm-bus.h>
+#include <linux/msm-bus-board.h>
 
 /* UART specific GENI registers */
 #define SE_UART_LOOPBACK_CFG		(0x22C)
@@ -95,6 +97,10 @@
 #define GENI_UART_NR_PORTS	(15)
 #define DEF_FIFO_DEPTH_WORDS	(16)
 #define DEF_FIFO_WIDTH_BITS	(32)
+#define UART_CORE2X_VOTE	(10000)
+#define DEFAULT_SE_CLK		(19200000)
+#define DEFAULT_BUS_WIDTH	(4)
+
 
 struct msm_geni_serial_port {
 	struct uart_port uport;
@@ -1257,6 +1263,25 @@
 	}
 
 	uport->dev = &pdev->dev;
+
+	if (!(of_property_read_u32(pdev->dev.of_node, "qcom,bus-mas",
+					&dev_port->serial_rsc.bus_mas))) {
+		dev_port->serial_rsc.bus_bw =
+				msm_bus_scale_register(
+					dev_port->serial_rsc.bus_mas,
+					MSM_BUS_SLAVE_EBI_CH0,
+					(char *)dev_name(&pdev->dev),
+					false);
+		if (IS_ERR_OR_NULL(dev_port->serial_rsc.bus_bw)) {
+			ret = PTR_ERR(dev_port->serial_rsc.bus_bw);
+			goto exit_geni_serial_probe;
+		}
+		dev_port->serial_rsc.ab = UART_CORE2X_VOTE;
+		dev_port->serial_rsc.ib = DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH;
+	} else {
+		dev_info(&pdev->dev, "No bus master specified");
+	}
+
 	dev_port->serial_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
 	if (IS_ERR(dev_port->serial_rsc.se_clk)) {
 		ret = PTR_ERR(dev_port->serial_rsc.se_clk);
@@ -1364,6 +1389,7 @@
 			(struct uart_driver *)port->uport.private_data;
 
 	uart_remove_one_port(drv, &port->uport);
+	msm_bus_scale_unregister(port->serial_rsc.bus_bw);
 	return 0;
 }
 
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index a0f161e..cb4387d 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -39,6 +39,7 @@
 	struct clk *m_ahb_clk;
 	struct clk *s_ahb_clk;
 	struct msm_bus_client_handle *bus_bw;
+	unsigned int bus_mas;
 	unsigned long ab;
 	unsigned long ib;
 	struct pinctrl *geni_pinctrl;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 867de7d..4b943cd 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1167,6 +1167,8 @@
 	struct capacity_state *cap_states; /* ptr to capacity state array */
 };
 
+extern bool sched_is_energy_aware(void);
+
 unsigned long capacity_curr_of(int cpu);
 
 struct sched_group;
diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c
index b0656b7..05dd2cb 100644
--- a/kernel/sched/energy.c
+++ b/kernel/sched/energy.c
@@ -56,6 +56,9 @@
 	int sd_level, i, nstates, cpu;
 	const __be32 *val;
 
+	if (!sched_is_energy_aware())
+		return;
+
 	for_each_possible_cpu(cpu) {
 		cn = of_get_cpu_node(cpu, NULL);
 		if (!cn) {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 2a8643c..6fb615e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5343,6 +5343,15 @@
 	return sched_feat(ENERGY_AWARE);
 }
 
+/*
+ * Externally visible function. Let's keep the one above
+ * so that the check is inlined/optimized in the sched paths.
+ */
+bool sched_is_energy_aware(void)
+{
+	return energy_aware();
+}
+
 struct energy_env {
 	struct sched_group	*sg_top;
 	struct sched_group	*sg_cap;
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index a088a55..b1c7852 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -49,6 +49,7 @@
 #include <linux/sched/deadline.h>
 #include <linux/timer.h>
 #include <linux/freezer.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 
@@ -1638,6 +1639,12 @@
 				raw_spin_unlock(&old_base->lock);
 				raw_spin_unlock(&new_base->lock);
 				cpu_relax();
+				/*
+				 * cpu_relax may just be a barrier. Grant the
+				 * run_hrtimer_list code some time to obtain
+				 * the spinlock.
+				 */
+				udelay(1);
 				raw_spin_lock(&new_base->lock);
 				raw_spin_lock_nested(&old_base->lock,
 							SINGLE_DEPTH_NESTING);
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 470d966..5463c3b 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1856,7 +1856,8 @@
 		spin_lock_irqsave(&new_base->lock, flags);
 		spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
 
-		BUG_ON(old_base->running_timer);
+		if (!cpu_online(cpu))
+			BUG_ON(old_base->running_timer);
 
 		for (i = 0; i < WHEEL_SIZE; i++)
 			migrate_timer_list(new_base, old_base->vectors + i,
diff --git a/sound/soc/msm/sdm845.c b/sound/soc/msm/sdm845.c
index 6987949..4f146cb 100644
--- a/sound/soc/msm/sdm845.c
+++ b/sound/soc/msm/sdm845.c
@@ -508,6 +508,8 @@
 	.key_code[7] = 0,
 	.linein_th = 5000,
 	.moisture_en = true,
+	.anc_micbias = MIC_BIAS_2,
+	.enable_anc_mic_detect = false,
 };
 
 static struct snd_soc_dapm_route wcd_audio_paths[] = {
@@ -4655,6 +4657,26 @@
 	},
 };
 
+static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
+	{
+		.name = MSM_DAILINK_NAME(ASM Loopback),
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name = "MultiMedia6",
+		.platform_name = "msm-pcm-loopback",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+	},
+};
+
 static struct snd_soc_dai_link msm_common_be_dai_links[] = {
 	/* Backend AFE DAI Links */
 	{
@@ -5373,6 +5395,7 @@
 static struct snd_soc_dai_link msm_tavil_snd_card_dai_links[
 			 ARRAY_SIZE(msm_common_dai_links) +
 			 ARRAY_SIZE(msm_tavil_fe_dai_links) +
+			 ARRAY_SIZE(msm_common_misc_fe_dai_links) +
 			 ARRAY_SIZE(msm_common_be_dai_links) +
 			 ARRAY_SIZE(msm_tavil_be_dai_links) +
 			 ARRAY_SIZE(msm_wcn_be_dai_links) +
@@ -5662,7 +5685,7 @@
 {
 	struct snd_soc_card *card = NULL;
 	struct snd_soc_dai_link *dailink;
-	int len_1, len_2, len_3;
+	int len_1, len_2, len_3, len_4;
 	int total_links;
 	const struct of_device_id *match;
 
@@ -5677,8 +5700,9 @@
 		card = &snd_soc_card_tavil_msm;
 		len_1 = ARRAY_SIZE(msm_common_dai_links);
 		len_2 = len_1 + ARRAY_SIZE(msm_tavil_fe_dai_links);
-		len_3 = len_2 + ARRAY_SIZE(msm_common_be_dai_links);
-		total_links = len_3 + ARRAY_SIZE(msm_tavil_be_dai_links);
+		len_3 = len_2 + ARRAY_SIZE(msm_common_misc_fe_dai_links);
+		len_4 = len_3 + ARRAY_SIZE(msm_common_be_dai_links);
+		total_links = len_4 + ARRAY_SIZE(msm_tavil_be_dai_links);
 		memcpy(msm_tavil_snd_card_dai_links,
 		       msm_common_dai_links,
 		       sizeof(msm_common_dai_links));
@@ -5686,9 +5710,12 @@
 		       msm_tavil_fe_dai_links,
 		       sizeof(msm_tavil_fe_dai_links));
 		memcpy(msm_tavil_snd_card_dai_links + len_2,
+		       msm_common_misc_fe_dai_links,
+		       sizeof(msm_common_misc_fe_dai_links));
+		memcpy(msm_tavil_snd_card_dai_links + len_3,
 		       msm_common_be_dai_links,
 		       sizeof(msm_common_be_dai_links));
-		memcpy(msm_tavil_snd_card_dai_links + len_3,
+		memcpy(msm_tavil_snd_card_dai_links + len_4,
 		       msm_tavil_be_dai_links,
 		       sizeof(msm_tavil_be_dai_links));
 
@@ -6186,14 +6213,19 @@
 			pdev->dev.of_node->full_name);
 		dev_dbg(&pdev->dev, "Jack type properties set to default");
 	} else {
-		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack"))
+		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
 			dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
-		else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack"))
+		} else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
 			dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
-		else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack"))
+		} else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
 			dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
-		else
+		} else {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
 			dev_dbg(&pdev->dev, "Unknown value, set to default");
+		}
 	}
 	/*
 	 * Parse US-Euro gpio info from DT. Report no error if us-euro