Merge "Merge remote-tracking branch '4.9/tmp-4979478' into msm-4.9" into msm-4.9
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt
index 96e42c5..6bf6a57 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt
@@ -218,7 +218,16 @@
 				master-id, slave-id, arbitrated bandwidth
 				in KBps, instantaneous bandwidth in KBps
 
-Example:
+The following are optional properties for client's device nodes:
+
+- qcom,msm-bus,alc-voter:	Boolean alc_voter flag to indicate that client
+				will vote as an Active Latency Client.
+- qcom,msm-bus,vectors-alc:	Arrays of unsigned integers representing:
+				first access latency, idle time in ns, this
+				property is required if qcom,msm-bus,alc-voter
+				is present.
+
+Example for default client:
 
 	qcom,msm-bus,name = "client-name";
 	qcom,msm-bus,num-cases = <3>;
@@ -229,3 +238,12 @@
 			<22 512 320000 3200000>, <26 512 3200000 3200000>,
 			<22 512 160000 1600000>, <26 512 1600000 1600000>;
 
+Example for ALC client:
+
+	qcom,msm-bus,name = "client-name";
+	qcom,msm-bus,num-cases = <2>;
+	qcom,msm-bus,active-only;
+	qcom,msm-bus,alc-voter;
+	qcom,msm-bus,vectors-alc =
+			<0 0>,
+			<500 1600>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
index a51f411..1702e80 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
@@ -191,6 +191,7 @@
 			cell-id = <MSM_BUS_BCM_QUP0>;
 			label = "QUP0";
 			qcom,bcm-name = "QUP0";
+			qcom,rscs = <&rsc_apps>;
 			qcom,bcm-dev;
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
new file mode 100644
index 0000000..fce1687
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	led_flash_rear: qcom,camera-flash@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+		qcom,torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+		qcom,switch-source = <&pmi8998_switch0>;
+		status = "ok";
+	};
+
+	led_flash_front: qcom,camera-flash@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-source = <&pmi8998_flash2>;
+		qcom,torch-source = <&pmi8998_torch2>;
+		qcom,switch-source = <&pmi8998_switch1>;
+		status = "ok";
+	};
+
+	actuator_regulator: gpio-regulator@0 {
+		compatible = "regulator-fixed";
+		reg = <0x0>;
+		regulator-name = "actuator_regulator";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		regulator-enable-ramp-delay = <100>;
+		enable-active-high;
+		gpio = <&tlmm 27 0>;
+		vin-supply = <&pmi8998_bob>;
+	};
+
+	camera_rear_ldo: gpio-regulator@1 {
+		compatible = "regulator-fixed";
+		reg = <0x1>;
+		regulator-name = "camera_rear_ldo";
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-enable-ramp-delay = <135>;
+		enable-active-high;
+		gpio = <&pm8998_gpios 12 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&camera_rear_dvdd_en_default>;
+		vin-supply = <&pm8998_s3>;
+	};
+
+	camera_ldo: gpio-regulator@2 {
+		compatible = "regulator-fixed";
+		reg = <0x2>;
+		regulator-name = "camera_ldo";
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-enable-ramp-delay = <233>;
+		enable-active-high;
+		gpio = <&pm8998_gpios 9 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&camera_dvdd_en_default>;
+		vin-supply = <&pm8998_s3>;
+	};
+};
+
+&cci {
+	actuator_rear: qcom,actuator@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&actuator_regulator>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+	};
+
+	actuator_front: qcom,actuator@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <1>;
+		cam_vaf-supply = <&actuator_regulator>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+	};
+
+	ois_rear: qcom,ois@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,ois";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&actuator_regulator>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+		status = "disabled";
+	};
+
+	eeprom_rear: qcom,eeprom@0 {
+		cell-index = <0>;
+		reg = <0>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_rear_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 80 0>,
+			<&tlmm 79 0>,
+			<&tlmm 27 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-vaf = <3>;
+		qcom,gpio-req-tbl-num = <0 1 2 3>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0",
+					"CAM_VANA0",
+					"CAM_VAF";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	eeprom_rear_aux: qcom,eeprom@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,eeprom";
+		cam_vdig-supply = <&camera_ldo>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+		qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+				 &cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+				 &cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 15 0>,
+			<&tlmm 9 0>,
+			<&tlmm 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1",
+					"CAM_VANA1";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	eeprom_front: qcom,eeprom@2 {
+		cell-index = <2>;
+		reg = <0x2>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				 &cam_sensor_front_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				 &cam_sensor_front_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>,
+			<&tlmm 8 0>,
+			<&tlmm 27 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-vaf = <3>;
+		qcom,gpio-req-tbl-num = <0 1 2 3>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					"CAM_RESET2",
+					"CAM_VANA2",
+					"CAM_VAF";
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@0 {
+		cell-index = <0>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x0>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,sensor-position-roll = <90>;
+		qcom,sensor-position-pitch = <0>;
+		qcom,sensor-position-yaw = <180>;
+		qcom,led-flash-src = <&led_flash_rear>;
+		qcom,actuator-src = <&actuator_rear>;
+		qcom,ois-src = <&ois_rear>;
+		qcom,eeprom-src = <&eeprom_rear>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_rear_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 80 0>,
+			<&tlmm 79 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0",
+					"CAM_VANA";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@1 {
+		cell-index = <1>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x1>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,sensor-position-roll = <90>;
+		qcom,sensor-position-pitch = <0>;
+		qcom,sensor-position-yaw = <180>;
+		qcom,eeprom-src = <&eeprom_rear_aux>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+		qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 15 0>,
+			<&tlmm 9 0>,
+			<&tlmm 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1",
+					"CAM_VANA1";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@2 {
+		cell-index = <2>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x02>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,sensor-position-roll = <90>;
+		qcom,sensor-position-pitch = <0>;
+		qcom,sensor-position-yaw = <0>;
+		qcom,eeprom-src = <&eeprom_front>;
+		qcom,actuator-src = <&actuator_front>;
+		qcom,led-flash-src = <&led_flash_front>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				 &cam_sensor_front_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				 &cam_sensor_front_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>,
+			<&tlmm 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					"CAM_RESET2",
+					"CAM_VANA1";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..fce1687
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	led_flash_rear: qcom,camera-flash@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+		qcom,torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+		qcom,switch-source = <&pmi8998_switch0>;
+		status = "ok";
+	};
+
+	led_flash_front: qcom,camera-flash@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-source = <&pmi8998_flash2>;
+		qcom,torch-source = <&pmi8998_torch2>;
+		qcom,switch-source = <&pmi8998_switch1>;
+		status = "ok";
+	};
+
+	actuator_regulator: gpio-regulator@0 {
+		compatible = "regulator-fixed";
+		reg = <0x0>;
+		regulator-name = "actuator_regulator";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		regulator-enable-ramp-delay = <100>;
+		enable-active-high;
+		gpio = <&tlmm 27 0>;
+		vin-supply = <&pmi8998_bob>;
+	};
+
+	camera_rear_ldo: gpio-regulator@1 {
+		compatible = "regulator-fixed";
+		reg = <0x1>;
+		regulator-name = "camera_rear_ldo";
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-enable-ramp-delay = <135>;
+		enable-active-high;
+		gpio = <&pm8998_gpios 12 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&camera_rear_dvdd_en_default>;
+		vin-supply = <&pm8998_s3>;
+	};
+
+	camera_ldo: gpio-regulator@2 {
+		compatible = "regulator-fixed";
+		reg = <0x2>;
+		regulator-name = "camera_ldo";
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-enable-ramp-delay = <233>;
+		enable-active-high;
+		gpio = <&pm8998_gpios 9 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&camera_dvdd_en_default>;
+		vin-supply = <&pm8998_s3>;
+	};
+};
+
+&cci {
+	actuator_rear: qcom,actuator@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&actuator_regulator>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+	};
+
+	actuator_front: qcom,actuator@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <1>;
+		cam_vaf-supply = <&actuator_regulator>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+	};
+
+	ois_rear: qcom,ois@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,ois";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&actuator_regulator>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+		status = "disabled";
+	};
+
+	eeprom_rear: qcom,eeprom@0 {
+		cell-index = <0>;
+		reg = <0>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_rear_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 80 0>,
+			<&tlmm 79 0>,
+			<&tlmm 27 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-vaf = <3>;
+		qcom,gpio-req-tbl-num = <0 1 2 3>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0",
+					"CAM_VANA0",
+					"CAM_VAF";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	eeprom_rear_aux: qcom,eeprom@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,eeprom";
+		cam_vdig-supply = <&camera_ldo>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+		qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+				 &cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+				 &cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 15 0>,
+			<&tlmm 9 0>,
+			<&tlmm 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1",
+					"CAM_VANA1";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	eeprom_front: qcom,eeprom@2 {
+		cell-index = <2>;
+		reg = <0x2>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				 &cam_sensor_front_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				 &cam_sensor_front_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>,
+			<&tlmm 8 0>,
+			<&tlmm 27 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-vaf = <3>;
+		qcom,gpio-req-tbl-num = <0 1 2 3>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					"CAM_RESET2",
+					"CAM_VANA2",
+					"CAM_VAF";
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@0 {
+		cell-index = <0>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x0>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,sensor-position-roll = <90>;
+		qcom,sensor-position-pitch = <0>;
+		qcom,sensor-position-yaw = <180>;
+		qcom,led-flash-src = <&led_flash_rear>;
+		qcom,actuator-src = <&actuator_rear>;
+		qcom,ois-src = <&ois_rear>;
+		qcom,eeprom-src = <&eeprom_rear>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_rear_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 80 0>,
+			<&tlmm 79 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0",
+					"CAM_VANA";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@1 {
+		cell-index = <1>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x1>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,sensor-position-roll = <90>;
+		qcom,sensor-position-pitch = <0>;
+		qcom,sensor-position-yaw = <180>;
+		qcom,eeprom-src = <&eeprom_rear_aux>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+		qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 15 0>,
+			<&tlmm 9 0>,
+			<&tlmm 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1",
+					"CAM_VANA1";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@2 {
+		cell-index = <2>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x02>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,sensor-position-roll = <90>;
+		qcom,sensor-position-pitch = <0>;
+		qcom,sensor-position-yaw = <0>;
+		qcom,eeprom-src = <&eeprom_front>;
+		qcom,actuator-src = <&actuator_front>;
+		qcom,led-flash-src = <&led_flash_front>;
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_ldo>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+		qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+		qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				 &cam_sensor_front_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				 &cam_sensor_front_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>,
+			<&tlmm 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					"CAM_RESET2",
+					"CAM_VANA1";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		qcom,clock-rates = <24000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index c197d65..cd9c8a8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -16,4 +16,213 @@
 		compatible = "qcom,cam-req-mgr";
 		status = "ok";
 	};
+
+	qcom,csiphy@ac65000 {
+		cell-index = <0>;
+		compatible = "qcom,csiphy-v1.0", "qcom,csiphy";
+		reg = <0x0ac65000 0x1000>;
+		reg-names = "csiphy";
+		interrupts = <0 477 0>;
+		interrupt-names = "csiphy";
+		gdscr-supply = <&titan_top_gdsc>;
+		qcom,cam-vreg-name = "gdscr";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8998_l26>;
+		clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
+			<&clock_camcc CAM_CC_CSIPHY0_CLK>,
+			<&clock_camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>,
+			<&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
+			<&clock_camcc CAM_CC_IFE_0_CSID_CLK>,
+			<&clock_camcc CAM_CC_IFE_0_CSID_CLK_SRC>;
+		clock-names = "camnoc_axi_clk",
+			"soc_ahb_clk",
+			"slow_ahb_src_clk",
+			"cpas_ahb_clk",
+			"cphy_rx_clk_src",
+			"csiphy0_clk",
+			"csi0phytimer_clk_src",
+			"csi0phytimer_clk",
+			"ife_0_csid_clk",
+			"ife_0_csid_clk_src";
+		qcom,clock-rates =
+			<0 0 80000000 0 320000000 0 269333333 0 0 384000000>;
+		status = "ok";
+	};
+
+	qcom,csiphy@ac66000{
+		cell-index = <1>;
+		compatible = "qcom,csiphy-v1.0", "qcom,csiphy";
+		reg = <0xac66000 0x1000>;
+		reg-names = "csiphy";
+		interrupts = <0 478 0>;
+		interrupt-names = "csiphy";
+		gdscr-supply = <&titan_top_gdsc>;
+		qcom,cam-vreg-name = "gdscr";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8998_l26>;
+		clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
+			<&clock_camcc CAM_CC_CSIPHY1_CLK>,
+			<&clock_camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>,
+			<&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
+			<&clock_camcc CAM_CC_IFE_1_CSID_CLK>,
+			<&clock_camcc CAM_CC_IFE_1_CSID_CLK_SRC>;
+		clock-names = "camnoc_axi_clk",
+			"soc_ahb_clk",
+			"slow_ahb_src_clk",
+			"cpas_ahb_clk",
+			"cphy_rx_clk_src",
+			"csiphy1_clk",
+			"csi1phytimer_clk_src",
+			"csi1phytimer_clk",
+			"ife_1_csid_clk",
+			"ife_1_csid_clk_src";
+		qcom,clock-rates =
+			<0 0 80000000 0 320000000 0 269333333 0 0 384000000>;
+
+		status = "ok";
+	};
+
+	qcom,csiphy@ac67000 {
+		cell-index = <2>;
+		compatible = "qcom,csiphy-v1.0", "qcom,csiphy";
+		reg = <0xac67000 0x1000>;
+		reg-names = "csiphy";
+		interrupts = <0 479 0>;
+		interrupt-names = "csiphy";
+		gdscr-supply = <&titan_top_gdsc>;
+		qcom,cam-vreg-name = "gdscr";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8998_l26>;
+		clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
+			<&clock_camcc CAM_CC_CSIPHY2_CLK>,
+			<&clock_camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>,
+			<&clock_camcc CAM_CC_CSI2PHYTIMER_CLK>,
+			<&clock_camcc CAM_CC_IFE_LITE_CSID_CLK>,
+			<&clock_camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>;
+		clock-names = "camnoc_axi_clk",
+			"soc_ahb_clk",
+			"slow_ahb_src_clk",
+			"cpas_ahb_clk",
+			"cphy_rx_clk_src",
+			"csiphy2_clk",
+			"csi2phytimer_clk_src",
+			"csi2phytimer_clk",
+			"ife_lite_csid_clk",
+			"ife_lite_csid_clk_src";
+		qcom,clock-rates =
+			<0 0 80000000 0 320000000 0 269333333 0 0 384000000>;
+		status = "ok";
+	};
+
+	cci: qcom,cci@ac4a000 {
+		cell-index = <0>;
+		compatible = "qcom,cci";
+		reg = <0xac4a000 0x4000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "cci";
+		interrupts = <0 460 0>;
+		interrupt-names = "cci";
+		status = "ok";
+		gdscr-supply = <&titan_top_gdsc>;
+		qcom,cam-vreg-name = "gdscr";
+		clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+			<&clock_camcc CAM_CC_SOC_AHB_CLK>,
+			<&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+			<&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+			<&clock_camcc CAM_CC_CCI_CLK>,
+			<&clock_camcc CAM_CC_CCI_CLK_SRC>;
+		clock-names = "camnoc_axi_clk",
+			"soc_ahb_clk",
+			"slow_ahb_src_clk",
+			"cpas_ahb_clk",
+			"cci_clk",
+			"cci_clk_src";
+		qcom,clock-rates = <0 0 80000000 0 0 37500000>;
+		pinctrl-names = "cci_default", "cci_suspend";
+		pinctrl-0 = <&cci0_active &cci1_active>;
+		pinctrl-1 = <&cci0_suspend &cci1_suspend>;
+		gpios = <&tlmm 17 0>,
+			<&tlmm 18 0>,
+			<&tlmm 19 0>,
+			<&tlmm 20 0>;
+		qcom,gpio-tbl-num = <0 1 2 3>;
+		qcom,gpio-tbl-flags = <1 1 1 1>;
+		qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+					"CCI_I2C_CLK0",
+					"CCI_I2C_DATA1",
+					"CCI_I2C_CLK1";
+
+		i2c_freq_100Khz: qcom,i2c_standard_mode {
+			qcom,hw-thigh = <201>;
+			qcom,hw-tlow = <174>;
+			qcom,hw-tsu-sto = <204>;
+			qcom,hw-tsu-sta = <231>;
+			qcom,hw-thd-dat = <22>;
+			qcom,hw-thd-sta = <162>;
+			qcom,hw-tbuf = <227>;
+			qcom,hw-scl-stretch-en = <0>;
+			qcom,hw-trdhld = <6>;
+			qcom,hw-tsp = <3>;
+			qcom,cci-clk-src = <37500000>;
+			status = "ok";
+		};
+
+		i2c_freq_400Khz: qcom,i2c_fast_mode {
+			qcom,hw-thigh = <38>;
+			qcom,hw-tlow = <56>;
+			qcom,hw-tsu-sto = <40>;
+			qcom,hw-tsu-sta = <40>;
+			qcom,hw-thd-dat = <22>;
+			qcom,hw-thd-sta = <35>;
+			qcom,hw-tbuf = <62>;
+			qcom,hw-scl-stretch-en = <0>;
+			qcom,hw-trdhld = <6>;
+			qcom,hw-tsp = <3>;
+			qcom,cci-clk-src = <37500000>;
+			status = "ok";
+		};
+
+		i2c_freq_custom: qcom,i2c_custom_mode {
+			qcom,hw-thigh = <38>;
+			qcom,hw-tlow = <56>;
+			qcom,hw-tsu-sto = <40>;
+			qcom,hw-tsu-sta = <40>;
+			qcom,hw-thd-dat = <22>;
+			qcom,hw-thd-sta = <35>;
+			qcom,hw-tbuf = <62>;
+			qcom,hw-scl-stretch-en = <1>;
+			qcom,hw-trdhld = <6>;
+			qcom,hw-tsp = <3>;
+			qcom,cci-clk-src = <37500000>;
+			status = "ok";
+		};
+
+		i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
+			qcom,hw-thigh = <16>;
+			qcom,hw-tlow = <22>;
+			qcom,hw-tsu-sto = <17>;
+			qcom,hw-tsu-sta = <18>;
+			qcom,hw-thd-dat = <16>;
+			qcom,hw-thd-sta = <15>;
+			qcom,hw-tbuf = <24>;
+			qcom,hw-scl-stretch-en = <0>;
+			qcom,hw-trdhld = <3>;
+			qcom,hw-tsp = <3>;
+			qcom,cci-clk-src = <37500000>;
+			status = "ok";
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 7f9351d..96ce5a8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -11,7 +11,7 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
-
+#include "sdm845-camera-sensor-cdp.dtsi"
 &soc {
 	sound-tavil {
 		qcom,us-euro-gpios = <&tavil_us_euro_sw>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index f7da384..e36ccf2 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -11,7 +11,7 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
-
+#include "sdm845-camera-sensor-mtp.dtsi"
 &soc {
 	gpio_keys {
 		compatible = "gpio-keys";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index a5ed9aa..bd09c7c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -2285,6 +2285,231 @@
 				};
 			};
 		};
+
+		cci0_active: cci0_active {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio17","gpio18"; // Only 2
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio17","gpio18";
+				bias-pull-up; /* PULL UP*/
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cci0_suspend: cci0_suspend {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio17","gpio18";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio17","gpio18";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cci1_active: cci1_active {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio19","gpio20";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio19","gpio20";
+				bias-pull-up; /* PULL UP*/
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cci1_suspend: cci1_suspend {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio19","gpio20";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio19","gpio20";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk0_active: cam_sensor_mclk0_active {
+			/* MCLK0 */
+			mux {
+				pins = "gpio13";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio13";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend {
+			/* MCLK0 */
+			mux {
+				pins = "gpio13";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio13";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_active: cam_sensor_rear_active {
+			/* RESET, AVDD LDO */
+			mux {
+				pins = "gpio80","gpio79";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio80","gpio79";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_suspend: cam_sensor_rear_suspend {
+			/* RESET, AVDD LDO */
+			mux {
+				pins = "gpio80","gpio79";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio80","gpio79";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk1_active: cam_sensor_mclk1_active {
+			/* MCLK1 */
+			mux {
+				pins = "gpio14";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio14";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend {
+			/* MCLK1 */
+			mux {
+				pins = "gpio14";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio14";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_front_active: cam_sensor_front_active {
+			/* RESET  AVDD_LDO*/
+			mux {
+				pins = "gpio28", "gpio8";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio28", "gpio8";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_front_suspend: cam_sensor_front_suspend {
+			/* RESET */
+			mux {
+				pins = "gpio28";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio28";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk2_active: cam_sensor_mclk2_active {
+			/* MCLK1 */
+			mux {
+				/* CLK, DATA */
+				pins = "gpio15";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio15";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk2_suspend: cam_sensor_mclk2_suspend {
+			/* MCLK1 */
+			mux {
+				/* CLK, DATA */
+				pins = "gpio15";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio15";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear2_active: cam_sensor_rear2_active {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio9","gpio8";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio9","gpio8";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio9","gpio8";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio9","gpio8";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
 	};
 };
 
@@ -2328,6 +2553,24 @@
 			power-source = <0>;
 		};
 	};
+
+	camera_dvdd_en {
+		camera_dvdd_en_default: camera_dvdd_en_default {
+			pins = "gpio9";
+			function = "normal";
+			power-source = <0>;
+			output-low;
+		};
+	};
+
+	camera_rear_dvdd_en {
+		camera_rear_dvdd_en_default: camera_rear_dvdd_en_default {
+			pins = "gpio12";
+			function = "normal";
+			power-source = <0>;
+			output-low;
+		};
+	};
 };
 
 &pmi8998_gpios {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
index af88108..2d181a4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
@@ -17,11 +17,13 @@
 &soc {
 	msm_vidc: qcom,vidc@aa00000 {
 		compatible = "qcom,msm-vidc";
-		status = "disabled";
+		status = "ok";
 		reg = <0xaa00000 0x200000>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		qcom,hfi = "venus";
 		qcom,firmware-name = "venus";
+		qcom,never-unload-fw;
+		qcom,sw-power-collapse;
 		qcom,max-secure-instances = <5>;
 		qcom,max-hw-load = <2563200>; /* Full 4k @ 60 + 1080p @ 60 */
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index f27f75b..259c5b7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1379,7 +1379,7 @@
 		compatible = "qcom,msm-watchdog";
 		reg = <0x17980000 0x1000>;
 		reg-names = "wdt-base";
-		interrupts = <0 3 0>, <0 4 0>;
+		interrupts = <0 0 0>, <0 1 0>;
 		qcom,bark-time = <11000>;
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index ac777b0..c44a9ea 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -701,6 +701,11 @@
 
 	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) {
+			pr_err("diag: In %s, unable to search command\n",
+			       __func__);
+			return NULL;
+		}
 		temp_entry = &item->entry;
 		if (temp_entry->cmd_code == entry->cmd_code &&
 		    temp_entry->subsys_id == entry->subsys_id &&
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 4f7c1e0..6685be3 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -983,8 +983,6 @@
 	}
 
 	if (fwd_info->buf_1 && !atomic_read(&fwd_info->buf_1->in_busy)) {
-		temp_buf = fwd_info->buf_1;
-		atomic_set(&temp_buf->in_busy, 1);
 		if (driver->feature[fwd_info->peripheral].encode_hdlc &&
 		    (fwd_info->type == TYPE_DATA ||
 		     fwd_info->type == TYPE_CMD)) {
@@ -994,9 +992,11 @@
 			read_buf = fwd_info->buf_1->data;
 			read_len = fwd_info->buf_1->len;
 		}
+		if (read_buf) {
+			temp_buf = fwd_info->buf_1;
+			atomic_set(&temp_buf->in_busy, 1);
+		}
 	} else if (fwd_info->buf_2 && !atomic_read(&fwd_info->buf_2->in_busy)) {
-		temp_buf = fwd_info->buf_2;
-		atomic_set(&temp_buf->in_busy, 1);
 		if (driver->feature[fwd_info->peripheral].encode_hdlc &&
 		    (fwd_info->type == TYPE_DATA ||
 		     fwd_info->type == TYPE_CMD)) {
@@ -1006,6 +1006,10 @@
 			read_buf = fwd_info->buf_2->data;
 			read_len = fwd_info->buf_2->len;
 		}
+		if (read_buf) {
+			temp_buf = fwd_info->buf_2;
+			atomic_set(&temp_buf->in_busy, 1);
+		}
 	} else {
 		pr_debug("diag: In %s, both buffers are empty for p: %d, t: %d\n",
 			 __func__, fwd_info->peripheral, fwd_info->type);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index a68da4e..5b59828 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -135,8 +135,7 @@
 			phys_enc);
 }
 
-static bool _sde_encoder_phys_is_ppsplit_slave(
-		struct sde_encoder_phys *phys_enc)
+static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
 {
 	enum sde_rm_topology_name topology;
 
@@ -144,8 +143,7 @@
 		return false;
 
 	topology = sde_connector_get_topology_name(phys_enc->connector);
-	if (topology == SDE_RM_TOPOLOGY_PPSPLIT &&
-			phys_enc->split_role == ENC_ROLE_SLAVE)
+	if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
 		return true;
 
 	return false;
@@ -199,6 +197,16 @@
 	return -ETIMEDOUT;
 }
 
+static bool _sde_encoder_phys_is_ppsplit_slave(
+		struct sde_encoder_phys *phys_enc)
+{
+	if (!phys_enc)
+		return false;
+
+	return _sde_encoder_phys_is_ppsplit(phys_enc) &&
+			phys_enc->split_role == ENC_ROLE_SLAVE;
+}
+
 static int _sde_encoder_phys_cmd_wait_for_idle(
 		struct sde_encoder_phys *phys_enc)
 {
@@ -463,13 +471,10 @@
 static bool sde_encoder_phys_cmd_needs_single_flush(
 		struct sde_encoder_phys *phys_enc)
 {
-	enum sde_rm_topology_name topology;
-
 	if (!phys_enc)
 		return false;
 
-	topology = sde_connector_get_topology_name(phys_enc->connector);
-	return topology == SDE_RM_TOPOLOGY_PPSPLIT;
+	return _sde_encoder_phys_is_ppsplit(phys_enc);
 }
 
 static int sde_encoder_phys_cmd_control_vblank_irq(
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index d278389..944faa3 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -810,7 +810,7 @@
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = &device->gmu;
 
-	if (!kgsl_gmu_isenabled(device))
+	if (!gmu->pdev)
 		return -EINVAL;
 
 	kgsl_gmu_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL,
@@ -837,7 +837,7 @@
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = &device->gmu;
 
-	if (!kgsl_gmu_isenabled(device))
+	if (!gmu->pdev)
 		return;
 
 	kgsl_gmu_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL,
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 366d8c3..c807c28 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -1,7 +1,7 @@
 /*
  * Device tree based initialization code for reserved memory.
  *
- * Copyright (c) 2013, 2015 The Linux Foundation. All Rights Reserved.
+ * Copyright (c) 2013, 2015, 2017 The Linux Foundation. All Rights Reserved.
  * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  * Author: Marek Szyprowski <m.szyprowski@samsung.com>
@@ -25,7 +25,7 @@
 #include <linux/sort.h>
 #include <linux/slab.h>
 
-#define MAX_RESERVED_REGIONS	16
+#define MAX_RESERVED_REGIONS	32
 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
 static int reserved_mem_count;
 
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 54a9cb2..3a6e214 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -144,4 +144,12 @@
 	  If you choose to build it as a module, it will be called
 	  msm_11ad_proxy.
 
+config SEEMP_CORE
+	tristate "SEEMP Core"
+	help
+	  This option enables QTI Snapdragron Smart Protection to detect
+	  anomalies in various activities. It records task activities in
+	  a log and rates the actions according to whether a typical user would
+	  use the tools.
+
 endmenu
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index 0bf87f4..cf24d7a 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -9,4 +9,5 @@
 obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o
 obj-$(CONFIG_MSM_MHI_DEV) += mhi_dev/
 obj-$(CONFIG_USB_BAM) += usb_bam.o
-obj-$(CONFIG_MSM_11AD) += msm_11ad/
\ No newline at end of file
+obj-$(CONFIG_MSM_11AD) += msm_11ad/
+obj-$(CONFIG_SEEMP_CORE) += seemp_core/
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 82c71353b..db3d6a4 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4163,6 +4163,7 @@
 		/* queue a work to start polling if don't have one */
 		atomic_set(&ipa3_ctx->transport_pm.eot_activity, 1);
 		if (!atomic_read(&ep->sys->curr_polling_state)) {
+			ipa3_inc_acquire_wakelock();
 			atomic_set(&ep->sys->curr_polling_state, 1);
 			queue_work(ep->sys->wq, &ep->sys->work);
 		}
diff --git a/drivers/platform/msm/seemp_core/Makefile b/drivers/platform/msm/seemp_core/Makefile
new file mode 100644
index 0000000..a26db43
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Iinclude/linux
+obj-$(CONFIG_SEEMP_CORE) += seemp_core.o
+seemp_core-objs:= seemp_logk.o seemp_ringbuf.o seemp_event_encoder.o
\ No newline at end of file
diff --git a/drivers/platform/msm/seemp_core/seemp_event_encoder.c b/drivers/platform/msm/seemp_core/seemp_event_encoder.c
new file mode 100644
index 0000000..6d9aa81
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_event_encoder.c
@@ -0,0 +1,179 @@
+/*
+ * 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/seemp_param_id.h>
+#include "seemp_logk.h"
+#include "seemp_event_encoder.h"
+
+static char *scan_id(char *s);
+static void encode_seemp_section(char *section_start, char *section_eq,
+				char *section_end, bool param, bool numeric,
+				int id, __s32 numeric_value);
+
+static void check_param_range(char *section_eq, bool param,
+	bool *numeric, int val_len, __s32 *numeric_value)
+{
+	long long_value = 0;
+
+	if (param && *numeric) {
+		/*check if 2 bytes & in[-99999,999999]*/
+		*numeric = (val_len >= 2) && (val_len <= 6);
+		if (*numeric) {
+			if (kstrtol(section_eq + 1, 10, &long_value)
+			!= 0) {
+				*numeric = false;
+			} else {
+				*numeric_value = (__s32)long_value;
+				/* We are checking whether the value
+				 * lies within 16bits
+				 */
+				*numeric = (long_value >= -32768) &&
+					(long_value <= 32767);
+			}
+		}
+	}
+}
+
+void encode_seemp_params(struct seemp_logk_blk *blk)
+{
+	struct seemp_logk_blk tmp;
+	char *s = 0;
+	char *msg_section_start = 0;
+	char *msg_section_eq = 0;
+	char *msg_s = 0;
+
+	memcpy(tmp.payload.msg, blk->payload.msg, BLK_MAX_MSG_SZ);
+	s = tmp.payload.msg + 1;
+	tmp.payload.msg[BLK_MAX_MSG_SZ - 1] = 0; /* zero-terminate */
+
+	while (true) {
+		char *section_start = s;
+		char *section_eq    = scan_id(s);
+		bool  param         = (section_eq - section_start >= 2) &&
+			(*section_eq == '=') && (section_eq[1] != ' ');
+		bool  numeric       = false;
+		int   id            = -1;
+		__s32 numeric_value = 0;
+		int id_len;
+		int val_len;
+		char ch;
+
+		if (param) {
+			id = param_id_index(section_start, section_eq);
+
+			if (id < 0)
+				param = false;
+		}
+
+		if (!param) {
+			s = section_eq;
+			while ((*s != 0) && (*s != ','))
+				s++;
+		} else {
+			s = section_eq + 1; /* equal sign */
+			numeric = (*s == '-') || ((*s >= '0') && (*s <= '9'));
+
+			if (numeric)
+				s++; /* first char of number */
+
+			while ((*s != 0) && (*s != ',')) {
+				if (*s == '=')
+					param   = false;
+				else if (!((*s >= '0') && (*s <= '9')))
+					numeric = false;
+
+				s++;
+			}
+
+			if (param) {
+				id_len  = section_eq - section_start;
+				val_len = s - (section_eq + 1);
+				param = (id_len >= 2) && (id_len <= 31)
+							&& (val_len <= 31);
+				ch = *s;
+				*s = 0;
+
+				check_param_range(section_eq, param,
+					&numeric, val_len, &numeric_value);
+				*s = ch;
+			}
+		}
+
+		msg_section_start = blk->payload.msg + (section_start -
+				tmp.payload.msg);
+		msg_section_eq = blk->payload.msg + (section_eq -
+				tmp.payload.msg);
+		msg_s = blk->payload.msg + (s - tmp.payload.msg);
+		encode_seemp_section(msg_section_start, msg_section_eq,
+				msg_s, param, numeric, id, numeric_value);
+
+		if (*s == 0)
+			break;
+
+		s++;
+	}
+
+	blk->len = s - blk->payload.msg;
+}
+
+static char *scan_id(char *s)
+{
+	while ((*s == '_') ||
+		((*s >= 'A') && (*s <= 'Z')) ||
+		((*s >= 'a') && (*s <= 'z'))) {
+		s++;
+	}
+
+	return s;
+}
+
+static void encode_seemp_section(char *section_start, char *section_eq,
+				char *section_end, bool param, bool numeric,
+				int id, __s32 numeric_value) {
+	param = param && (section_eq + 1 < section_end);
+
+	if (!param) {
+		/* Encode skip section */
+		int  skip_len	= section_end - section_start;
+		char skip_len_hi = skip_len & 0xE0;
+		char skip_len_lo = skip_len & 0x1F;
+
+		if (skip_len < 32) {
+			section_start[-1] = 0xC0 | skip_len_lo;
+							/* [1:1:0:0 0000] */
+		} else {
+			section_start[-1] = 0xE0 | skip_len_lo;
+							/* [1:1:1:0 0000] */
+
+			if (skip_len_hi & 0x20)
+				section_start[0] |= 0x80;
+
+			if (skip_len_hi & 0x40)
+				section_start[1] |= 0x80;
+
+			if (skip_len_hi & 0x80)
+				section_start[2] |= 0x80;
+		}
+	} else {
+		/* Encode ID=VALUE section */
+		char id_len            = section_eq  - section_start;
+		char value_len         = section_end - (section_eq + 1);
+
+		section_start[-1]      = 0x00 | id_len;
+		*(__s16 *)section_start = id;
+		section_eq[0]          = (!numeric ? 0x80 : 0x00) | value_len;
+
+		if (numeric)
+			*(__s16 *)(section_eq + 1) = numeric_value;
+	}
+}
diff --git a/drivers/platform/msm/seemp_core/seemp_event_encoder.h b/drivers/platform/msm/seemp_core/seemp_event_encoder.h
new file mode 100644
index 0000000..7cb7274
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_event_encoder.h
@@ -0,0 +1,21 @@
+/*
+ * 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SEEMP_EVENT_ENCODER_H__
+#define __SEEMP_EVENT_ENCODER_H__
+
+#include "seemp_logk.h"
+
+void encode_seemp_params(struct seemp_logk_blk *blk);
+
+#endif /* __SEEMP_EVENT_ENCODER_H__ */
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c
new file mode 100644
index 0000000..ce073ed
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_logk.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2014-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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "seemp: %s: " fmt, __func__
+
+#include "seemp_logk.h"
+#include "seemp_ringbuf.h"
+
+#ifndef VM_RESERVED
+#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
+#endif
+
+#define MASK_BUFFER_SIZE 256
+#define FOUR_MB 4
+#define YEAR_BASE 1900
+
+static struct seemp_logk_dev *slogk_dev;
+
+static unsigned int ring_sz = FOUR_MB;
+
+/*
+ * default is besteffort, apps do not get blocked
+ */
+static unsigned int block_apps;
+
+
+/*
+ * When this flag is turned on,
+ * kmalloc should be used for ring buf allocation
+ * otherwise it is vmalloc.
+ * default is to use vmalloc
+ * kmalloc has a limit of 4MB
+ */
+unsigned int kmalloc_flag;
+
+static struct class *cl;
+
+static rwlock_t filter_lock;
+static struct seemp_source_mask *pmask;
+static unsigned int num_sources;
+
+static long seemp_logk_reserve_rdblks(
+		struct seemp_logk_dev *sdev, unsigned long arg);
+static long seemp_logk_set_mask(unsigned long arg);
+static long seemp_logk_set_mapping(unsigned long arg);
+static long seemp_logk_check_filter(unsigned long arg);
+
+void* (*seemp_logk_kernel_begin)(char **buf);
+
+void (*seemp_logk_kernel_end)(void *blck);
+
+/*
+ * the last param is the permission bits *
+ * kernel logging is done in three steps:
+ * (1)  fetch a block, fill everything except payload.
+ * (2)  return payload pointer to the caller.
+ * (3)  caller fills its data directly into the payload area.
+ * (4)  caller invoked finish_record(), to finish writing.
+ */
+void *seemp_logk_kernel_start_record(char **buf)
+{
+	struct seemp_logk_blk *blk;
+	struct timespec now;
+	struct tm ts;
+	int idx;
+	int ret;
+
+	DEFINE_WAIT(write_wait);
+
+	ret = 0;
+	idx = 0;
+	now = current_kernel_time();
+	blk = ringbuf_fetch_wr_block(slogk_dev);
+	if (!blk) {
+		/*
+		 * there is no blk to write
+		 * if block_apps == 0; quietly return
+		 */
+		if (!block_apps) {
+			*buf = NULL;
+			return NULL;
+		}
+		/*else wait for the blks to be available*/
+		while (1) {
+			mutex_lock(&slogk_dev->lock);
+			prepare_to_wait(&slogk_dev->writers_wq,
+				&write_wait, TASK_INTERRUPTIBLE);
+			ret = (slogk_dev->num_write_avail_blks <= 0);
+			if (!ret) {
+				/* don't have to wait*/
+				break;
+			}
+			mutex_unlock(&slogk_dev->lock);
+			if (signal_pending(current)) {
+				ret = -EINTR;
+				break;
+			}
+			schedule();
+		}
+
+		finish_wait(&slogk_dev->writers_wq, &write_wait);
+		if (ret)
+			return NULL;
+
+		idx = slogk_dev->write_idx;
+		slogk_dev->write_idx =
+			(slogk_dev->write_idx + 1) % slogk_dev->num_tot_blks;
+		slogk_dev->num_write_avail_blks--;
+		slogk_dev->num_write_in_prog_blks++;
+		slogk_dev->num_writers++;
+
+		blk = &slogk_dev->ring[idx];
+		/*mark block invalid*/
+		blk->status = 0x0;
+		mutex_unlock(&slogk_dev->lock);
+	}
+
+	blk->version = OBSERVER_VERSION;
+	blk->pid = current->tgid;
+	blk->tid = current->pid;
+	blk->uid = (current_uid()).val;
+	blk->sec = now.tv_sec;
+	blk->nsec = now.tv_nsec;
+	strlcpy(blk->appname, current->comm, TASK_COMM_LEN);
+	time_to_tm(now.tv_sec, 0, &ts);
+	ts.tm_year += YEAR_BASE;
+	ts.tm_mon += 1;
+
+	snprintf(blk->ts, TS_SIZE, "%04ld-%02d-%02d %02d:%02d:%02d",
+			ts.tm_year, ts.tm_mon, ts.tm_mday,
+			ts.tm_hour, ts.tm_min, ts.tm_sec);
+
+	*buf = blk->payload.msg;
+
+	return blk;
+}
+
+void seemp_logk_kernel_end_record(void *blck)
+{
+	struct seemp_logk_blk *blk = (struct seemp_logk_blk *)blck;
+
+	if (blk) {
+		/*update status at the very end*/
+		blk->status |= 0x1;
+		blk->uid =  (current_uid()).val;
+
+		ringbuf_finish_writer(slogk_dev, blk);
+	}
+}
+
+static int seemp_logk_usr_record(const char __user *buf, size_t count)
+{
+	struct seemp_logk_blk *blk;
+	struct seemp_logk_blk usr_blk;
+	struct seemp_logk_blk *local_blk;
+	struct timespec now;
+	struct tm ts;
+	int idx, ret;
+
+	DEFINE_WAIT(write_wait);
+
+	if (buf) {
+		local_blk = (struct seemp_logk_blk *)buf;
+		if (copy_from_user(&usr_blk.pid, &local_blk->pid,
+					sizeof(usr_blk.pid)) != 0)
+			return -EFAULT;
+		if (copy_from_user(&usr_blk.tid, &local_blk->tid,
+					sizeof(usr_blk.tid)) != 0)
+			return -EFAULT;
+		if (copy_from_user(&usr_blk.uid, &local_blk->uid,
+					sizeof(usr_blk.uid)) != 0)
+			return -EFAULT;
+		if (copy_from_user(&usr_blk.len, &local_blk->len,
+					sizeof(usr_blk.len)) != 0)
+			return -EFAULT;
+		if (copy_from_user(&usr_blk.payload, &local_blk->payload,
+					sizeof(struct blk_payload)) != 0)
+			return -EFAULT;
+	} else {
+		return -EFAULT;
+	}
+	idx = ret = 0;
+	now = current_kernel_time();
+	blk = ringbuf_fetch_wr_block(slogk_dev);
+	if (!blk) {
+		if (!block_apps)
+			return 0;
+		while (1) {
+			mutex_lock(&slogk_dev->lock);
+			prepare_to_wait(&slogk_dev->writers_wq,
+					&write_wait,
+					TASK_INTERRUPTIBLE);
+			ret = (slogk_dev->num_write_avail_blks <= 0);
+			if (!ret)
+				break;
+			mutex_unlock(&slogk_dev->lock);
+			if (signal_pending(current)) {
+				ret = -EINTR;
+				break;
+			}
+			schedule();
+		}
+		finish_wait(&slogk_dev->writers_wq, &write_wait);
+		if (ret)
+			return -EINTR;
+
+		idx = slogk_dev->write_idx;
+		slogk_dev->write_idx =
+			(slogk_dev->write_idx + 1) % slogk_dev->num_tot_blks;
+		slogk_dev->num_write_avail_blks--;
+		slogk_dev->num_write_in_prog_blks++;
+		slogk_dev->num_writers++;
+		blk = &slogk_dev->ring[idx];
+		/*mark block invalid*/
+		blk->status = 0x0;
+		mutex_unlock(&slogk_dev->lock);
+	}
+	if (usr_blk.len > sizeof(struct blk_payload)-1)
+		usr_blk.len = sizeof(struct blk_payload)-1;
+
+	memcpy(&blk->payload, &usr_blk.payload, sizeof(struct blk_payload));
+	blk->pid = usr_blk.pid;
+	blk->uid = usr_blk.uid;
+	blk->tid = usr_blk.tid;
+	blk->sec = now.tv_sec;
+	blk->nsec = now.tv_nsec;
+	time_to_tm(now.tv_sec, 0, &ts);
+	ts.tm_year += YEAR_BASE;
+	ts.tm_mon += 1;
+	snprintf(blk->ts, TS_SIZE, "%02ld-%02d-%02d %02d:%02d:%02d",
+			ts.tm_year, ts.tm_mon, ts.tm_mday,
+			ts.tm_hour, ts.tm_min, ts.tm_sec);
+	strlcpy(blk->appname, current->comm, TASK_COMM_LEN);
+	blk->status |= 0x1;
+	ringbuf_finish_writer(slogk_dev, blk);
+	return ret;
+}
+
+static void seemp_logk_attach(void)
+{
+	seemp_logk_kernel_end = seemp_logk_kernel_end_record;
+	seemp_logk_kernel_begin = seemp_logk_kernel_start_record;
+}
+
+static void seemp_logk_detach(void)
+{
+	seemp_logk_kernel_begin = NULL;
+	seemp_logk_kernel_end = NULL;
+}
+
+static ssize_t
+seemp_logk_write(struct file *file, const char __user *buf, size_t count,
+		loff_t *ppos)
+{
+	return seemp_logk_usr_record(buf, count);
+}
+
+static int
+seemp_logk_open(struct inode *inode, struct file *filp)
+{
+	int ret;
+
+	/*disallow seeks on this file*/
+	ret = nonseekable_open(inode, filp);
+	if (ret) {
+		pr_err("ret= %d\n", ret);
+		return ret;
+	}
+
+	slogk_dev->minor = iminor(inode);
+	filp->private_data = slogk_dev;
+
+	return 0;
+}
+
+static bool seemp_logk_get_bit_from_vector(__u8 *pVec, __u32 index)
+{
+	unsigned int byte_num = index/8;
+	unsigned int bit_num = index%8;
+	unsigned char byte;
+
+	if (DIV_ROUND_UP(index, 8) > MASK_BUFFER_SIZE)
+		return false;
+
+	byte = pVec[byte_num];
+
+	return !(byte & (1 << bit_num));
+}
+
+static long seemp_logk_ioctl(struct file *filp, unsigned int cmd,
+		unsigned long arg)
+{
+	struct seemp_logk_dev *sdev;
+	int ret;
+
+	sdev = (struct seemp_logk_dev *) filp->private_data;
+
+	if (cmd == SEEMP_CMD_RESERVE_RDBLKS) {
+		return seemp_logk_reserve_rdblks(sdev, arg);
+	} else if (cmd == SEEMP_CMD_RELEASE_RDBLKS) {
+		mutex_lock(&sdev->lock);
+		sdev->read_idx = (sdev->read_idx + sdev->num_read_in_prog_blks)
+			% sdev->num_tot_blks;
+		sdev->num_write_avail_blks += sdev->num_read_in_prog_blks;
+		ret = sdev->num_read_in_prog_blks;
+		sdev->num_read_in_prog_blks = 0;
+		/*wake up any waiting writers*/
+		mutex_unlock(&sdev->lock);
+		if (ret && block_apps)
+			wake_up_interruptible(&sdev->writers_wq);
+	} else if (cmd == SEEMP_CMD_GET_RINGSZ) {
+		if (copy_to_user((unsigned int *)arg, &sdev->ring_sz,
+				sizeof(unsigned int)))
+			return -EFAULT;
+	} else if (cmd == SEEMP_CMD_GET_BLKSZ) {
+		if (copy_to_user((unsigned int *)arg, &sdev->blk_sz,
+				sizeof(unsigned int)))
+			return -EFAULT;
+	} else if (cmd == SEEMP_CMD_SET_MASK) {
+		return seemp_logk_set_mask(arg);
+	} else if (cmd == SEEMP_CMD_SET_MAPPING) {
+		return seemp_logk_set_mapping(arg);
+	} else if (cmd == SEEMP_CMD_CHECK_FILTER) {
+		return seemp_logk_check_filter(arg);
+	}
+	pr_err("Invalid Request %X\n", cmd);
+	return -ENOIOCTLCMD;
+}
+
+static long seemp_logk_reserve_rdblks(
+		struct seemp_logk_dev *sdev, unsigned long arg)
+{
+	int ret;
+	struct read_range rrange;
+
+	DEFINE_WAIT(read_wait);
+
+	mutex_lock(&sdev->lock);
+	if (sdev->num_writers > 0 || sdev->num_read_avail_blks <= 0) {
+		ret = -EPERM;
+		pr_debug("(reserve): blocking, cannot read.\n");
+		pr_debug("num_writers=%d num_read_avail_blks=%d\n",
+		sdev->num_writers,
+				sdev->num_read_avail_blks);
+		mutex_unlock(&sdev->lock);
+		/*
+		 * unlock the device
+		 * wait on a wait queue
+		 * after wait, grab the dev lock again
+		 */
+		while (1) {
+			mutex_lock(&sdev->lock);
+			prepare_to_wait(&sdev->readers_wq, &read_wait,
+					TASK_INTERRUPTIBLE);
+			ret = (sdev->num_writers > 0 ||
+					sdev->num_read_avail_blks <= 0);
+			if (!ret) {
+				/*don't have to wait*/
+				break;
+			}
+			mutex_unlock(&sdev->lock);
+			if (signal_pending(current)) {
+				ret = -EINTR;
+				break;
+			}
+			schedule();
+		}
+
+		finish_wait(&sdev->readers_wq, &read_wait);
+		if (ret)
+			return -EINTR;
+	}
+
+	/*sdev->lock is held at this point*/
+	sdev->num_read_in_prog_blks = sdev->num_read_avail_blks;
+	sdev->num_read_avail_blks = 0;
+	rrange.start_idx = sdev->read_idx;
+	rrange.num = sdev->num_read_in_prog_blks;
+	mutex_unlock(&sdev->lock);
+
+	if (copy_to_user((unsigned int *)arg, &rrange,
+			sizeof(struct read_range)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static long seemp_logk_set_mask(unsigned long arg)
+{
+	__u8 buffer[256];
+	int i;
+	unsigned int num_elements;
+
+	if (copy_from_user(&num_elements,
+		(unsigned int __user *) arg, sizeof(unsigned int)))
+		return -EFAULT;
+
+	read_lock(&filter_lock);
+	if (num_sources == 0) {
+		read_unlock(&filter_lock);
+		return -EINVAL;
+	}
+
+	if (num_elements == 0 ||
+		DIV_ROUND_UP(num_sources, 8) > MASK_BUFFER_SIZE) {
+		read_unlock(&filter_lock);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(buffer,
+			(__u8 *)arg, DIV_ROUND_UP(num_sources, 8))) {
+		read_unlock(&filter_lock);
+		return -EFAULT;
+	}
+
+	read_unlock(&filter_lock);
+	write_lock(&filter_lock);
+	if (num_elements != num_sources) {
+		write_unlock(&filter_lock);
+		return -EPERM;
+	}
+
+	for (i = 0; i < num_sources; i++) {
+		pmask[i].isOn =
+				seemp_logk_get_bit_from_vector(
+					(__u8 *)buffer, i);
+	}
+	write_unlock(&filter_lock);
+	return 0;
+}
+
+static long seemp_logk_set_mapping(unsigned long arg)
+{
+	__u32 num_elements;
+	__u32 *pbuffer;
+	int i;
+	struct seemp_source_mask *pnewmask;
+
+	if (copy_from_user(&num_elements,
+					(__u32 __user *)arg, sizeof(__u32)))
+		return -EFAULT;
+
+	if ((num_elements == 0) || (num_elements >
+		(UINT_MAX / sizeof(struct seemp_source_mask))))
+		return -EFAULT;
+
+	write_lock(&filter_lock);
+	if (pmask != NULL) {
+		/*
+		 * Mask is getting set again.
+		 * seemp_core was probably restarted.
+		 */
+		struct seemp_source_mask *ptempmask;
+
+		num_sources = 0;
+		ptempmask = pmask;
+		pmask = NULL;
+		kfree(ptempmask);
+	}
+	write_unlock(&filter_lock);
+	pbuffer = kmalloc(sizeof(struct seemp_source_mask)
+				* num_elements, GFP_KERNEL);
+	if (pbuffer == NULL)
+		return -ENOMEM;
+
+	/*
+	 * Use our new table as scratch space for now.
+	 * We copy an ordered list of hash values into our buffer.
+	 */
+	if (copy_from_user(pbuffer, &((__u32 __user *)arg)[1],
+					num_elements*sizeof(unsigned int))) {
+		kfree(pbuffer);
+		return -EFAULT;
+	}
+	/*
+	 * We arrange the user data into a more usable form.
+	 * This is done in-place.
+	 */
+	pnewmask = (struct seemp_source_mask *) pbuffer;
+	for (i = num_elements - 1; i >= 0; i--) {
+		pnewmask[i].hash = pbuffer[i];
+		/* Observer is off by default*/
+		pnewmask[i].isOn = 0;
+	}
+	write_lock(&filter_lock);
+	pmask = pnewmask;
+	num_sources = num_elements;
+	write_unlock(&filter_lock);
+	return 0;
+}
+
+static long seemp_logk_check_filter(unsigned long arg)
+{
+	int i;
+	unsigned int hash = (unsigned int) arg;
+
+	/*
+	 * This lock may be a bit long.
+	 * If it is a problem, it can be fixed.
+	 */
+	read_lock(&filter_lock);
+	for (i = 0; i < num_sources; i++) {
+		if (hash == pmask[i].hash) {
+			int result = pmask[i].isOn;
+
+			read_unlock(&filter_lock);
+			return result;
+		}
+	}
+	read_unlock(&filter_lock);
+	return 0;
+}
+
+static int seemp_logk_mmap(struct file *filp,
+		struct vm_area_struct *vma)
+{
+	int ret;
+	char *vptr;
+	unsigned long length, pfn;
+	unsigned long start = vma->vm_start;
+
+	length = vma->vm_end - vma->vm_start;
+
+	if (length > (unsigned long) slogk_dev->ring_sz) {
+		pr_err("len check failed\n");
+		return -EIO;
+	}
+
+	vma->vm_flags |= VM_RESERVED | VM_SHARED;
+	vptr = (char *) slogk_dev->ring;
+	ret = 0;
+
+	if (kmalloc_flag) {
+		ret = remap_pfn_range(vma,
+				start,
+				virt_to_phys((void *)
+				((unsigned long)slogk_dev->ring)) >> PAGE_SHIFT,
+				length,
+				vma->vm_page_prot);
+		if (ret != 0) {
+			pr_err("remap_pfn_range() fails with ret = %d\n",
+				ret);
+			return -EAGAIN;
+		}
+	} else {
+		while (length > 0) {
+			pfn = vmalloc_to_pfn(vptr);
+
+			ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE,
+					vma->vm_page_prot);
+			if (ret < 0) {
+				pr_err("remap_pfn_range() fails with ret = %d\n",
+					ret);
+				return ret;
+			}
+			start += PAGE_SIZE;
+			vptr += PAGE_SIZE;
+			length -= PAGE_SIZE;
+		}
+	}
+
+	return 0;
+}
+
+static const struct file_operations seemp_logk_fops = {
+	.write = seemp_logk_write,
+	.open = seemp_logk_open,
+	.unlocked_ioctl = seemp_logk_ioctl,
+	.compat_ioctl = seemp_logk_ioctl,
+	.mmap = seemp_logk_mmap,
+};
+
+__init int seemp_logk_init(void)
+{
+	int ret;
+	int devno = 0;
+
+	num_sources = 0;
+	kmalloc_flag = 0;
+	block_apps = 0;
+	pmask = NULL;
+
+	if (kmalloc_flag && ring_sz > FOUR_MB) {
+		pr_err("kmalloc cannot allocate > 4MB\n");
+		return -ENOMEM;
+	}
+
+	ring_sz = ring_sz * SZ_1M;
+	if (ring_sz <= 0) {
+		pr_err("Too small a ring_sz=%d\n", ring_sz);
+		return -EINVAL;
+	}
+
+	slogk_dev = kmalloc(sizeof(*slogk_dev), GFP_KERNEL);
+	if (slogk_dev == NULL)
+		return -ENOMEM;
+
+	slogk_dev->ring_sz = ring_sz;
+	slogk_dev->blk_sz = sizeof(struct seemp_logk_blk);
+	/*initialize ping-pong buffers*/
+	ret = ringbuf_init(slogk_dev);
+	if (ret < 0) {
+		pr_err("Init Failed, ret = %d\n", ret);
+		goto pingpong_fail;
+	}
+
+	ret = alloc_chrdev_region(&devno, 0, seemp_LOGK_NUM_DEVS,
+			seemp_LOGK_DEV_NAME);
+	if (ret < 0) {
+		pr_err("alloc_chrdev_region failed with ret = %d\n",
+				ret);
+		goto register_fail;
+	}
+
+	slogk_dev->major = MAJOR(devno);
+
+	pr_debug("logk: major# = %d\n", slogk_dev->major);
+
+	cl = class_create(THIS_MODULE, seemp_LOGK_DEV_NAME);
+	if (cl == NULL) {
+		pr_err("class create failed");
+		goto cdev_fail;
+	}
+	if (device_create(cl, NULL, devno, NULL,
+			seemp_LOGK_DEV_NAME) == NULL) {
+		pr_err("device create failed");
+		goto class_destroy_fail;
+	}
+	cdev_init(&(slogk_dev->cdev), &seemp_logk_fops);
+
+	slogk_dev->cdev.owner = THIS_MODULE;
+	ret = cdev_add(&(slogk_dev->cdev), MKDEV(slogk_dev->major, 0), 1);
+	if (ret) {
+		pr_err("cdev_add failed with ret = %d", ret);
+		goto class_destroy_fail;
+	}
+
+	seemp_logk_attach();
+	mutex_init(&slogk_dev->lock);
+	init_waitqueue_head(&slogk_dev->readers_wq);
+	init_waitqueue_head(&slogk_dev->writers_wq);
+	rwlock_init(&filter_lock);
+	return 0;
+class_destroy_fail:
+	class_destroy(cl);
+cdev_fail:
+	unregister_chrdev_region(devno, seemp_LOGK_NUM_DEVS);
+register_fail:
+	ringbuf_cleanup(slogk_dev);
+pingpong_fail:
+	kfree(slogk_dev);
+	return -EPERM;
+}
+
+__exit void seemp_logk_cleanup(void)
+{
+	dev_t devno = MKDEV(slogk_dev->major, slogk_dev->minor);
+
+	seemp_logk_detach();
+
+	cdev_del(&slogk_dev->cdev);
+
+	unregister_chrdev_region(devno, seemp_LOGK_NUM_DEVS);
+	ringbuf_cleanup(slogk_dev);
+	kfree(slogk_dev);
+
+	if (pmask != NULL) {
+		kfree(pmask);
+		pmask = NULL;
+	}
+}
+
+module_init(seemp_logk_init);
+module_exit(seemp_logk_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("seemp Observer");
+
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.h b/drivers/platform/msm/seemp_core/seemp_logk.h
new file mode 100644
index 0000000..1a41d4c
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_logk.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014-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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SEEMP_LOGK_H__
+#define __SEEMP_LOGK_H__
+
+#define OBSERVER_VERSION 0x01
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <asm/ioctls.h>
+
+#define seemp_LOGK_NUM_DEVS 1
+#define seemp_LOGK_DEV_NAME "seemplog"
+
+/*
+ * The logcat driver on Android uses four 256k ring buffers
+ * here, we use two ring buffers of the same size.
+ * we think this is reasonable
+ */
+#define FULL_BUF_SIZE (64 * 1024 * 1024)
+#define HALF_BUF_SIZE (32 * 1024 * 1024)
+#define FULL_BLOCKS (8 * 1024)
+#define HALF_BLOCKS (4 * 1024)
+
+#define READER_NOT_READY 0
+#define READER_READY 1
+
+#define MAGIC 'z'
+
+#define SEEMP_CMD_RESERVE_RDBLKS     _IOR(MAGIC, 1, int)
+#define SEEMP_CMD_RELEASE_RDBLKS     _IO(MAGIC, 2)
+#define SEEMP_CMD_GET_RINGSZ     _IOR(MAGIC, 3, int)
+#define SEEMP_CMD_GET_BLKSZ     _IOR(MAGIC, 4, int)
+#define SEEMP_CMD_SET_MASK          _IO(MAGIC, 5)
+#define SEEMP_CMD_SET_MAPPING       _IO(MAGIC, 6)
+#define SEEMP_CMD_CHECK_FILTER      _IOR(MAGIC, 7, int)
+
+struct read_range {
+	int start_idx;
+	int num;
+};
+
+struct seemp_logk_dev {
+	unsigned int major;
+	unsigned int minor;
+
+	struct cdev cdev;
+	struct class *cls;
+	/*the full buffer*/
+	struct seemp_logk_blk *ring;
+	/*an array of blks*/
+	unsigned int ring_sz;
+	unsigned int blk_sz;
+
+	int num_tot_blks;
+
+	int num_write_avail_blks;
+	int num_write_in_prog_blks;
+
+	int num_read_avail_blks;
+	int num_read_in_prog_blks;
+
+	int num_writers;
+
+	/*
+	 * there is always one reader
+	 * which is the observer daemon
+	 * therefore there is no necessity
+	 * for num_readers variable
+	 */
+
+	/*
+	 * read_idx  and write_idx loop through from zero to ring_sz,
+	 * and then back to zero in a circle, as they advance
+	 * based on the reader's and writers' accesses
+	 */
+	int read_idx;
+
+	int write_idx;
+
+	/*
+	 * wait queues
+	 * readers_wq: implement wait for readers
+	 * writers_wq: implement wait for writers
+	 *
+	 * whether writers are blocked or not is driven by the policy:
+	 * case 1: (best_effort_logging == 1)
+	 *         writers are not blocked, and
+	 *         when there is no mem in the ring to store logs,
+	 *         the logs are simply dropped.
+	 * case 2: (best_effort_logging == 0)
+	 *         when there is no mem in the ring to store logs,
+	 *         the process gets blocked until there is space.
+	 */
+	wait_queue_head_t readers_wq;
+	wait_queue_head_t writers_wq;
+
+	/*
+	 * protects everything in the device
+	 * including ring buffer and all the num_ variables
+	 * spinlock_t lock;
+	 */
+	struct mutex lock;
+};
+
+#define BLK_SIZE       256
+#define BLK_HDR_SIZE   64
+#define TS_SIZE        20
+#define BLK_MAX_MSG_SZ (BLK_SIZE - BLK_HDR_SIZE)
+
+struct blk_payload {
+	__u32 api_id;  /* event API id */
+	char  msg[BLK_MAX_MSG_SZ]; /* event parameters */
+} __packed;
+
+struct seemp_logk_blk {
+	__u8  status;  /* bits: 0->valid/invalid; 1-7: unused as of now! */
+	__u16 len;     /* length of the payload */
+	__u8  version; /* version number */
+	__s32 pid;     /* generating process's pid */
+	__s32 uid;     /* generating process's uid - app specific */
+	__s32 tid;     /* generating process's tid */
+	__s32 sec;     /* seconds since Epoch */
+	__s32 nsec;    /* nanoseconds */
+	char        ts[TS_SIZE];  /* Time Stamp */
+	char        appname[TASK_COMM_LEN];
+	struct blk_payload payload;
+} __packed;
+
+
+extern unsigned int kmalloc_flag;
+
+struct seemp_source_mask {
+	__u32       hash;
+	bool        isOn;
+};
+#endif
diff --git a/drivers/platform/msm/seemp_core/seemp_ringbuf.c b/drivers/platform/msm/seemp_core/seemp_ringbuf.c
new file mode 100644
index 0000000..4558051
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_ringbuf.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014-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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "seemp: %s: " fmt, __func__
+
+#include "seemp_logk.h"
+#include "seemp_ringbuf.h"
+#include "seemp_event_encoder.h"
+
+/*initial function no need to hold ring_lock*/
+int ringbuf_init(struct seemp_logk_dev *sdev)
+{
+	char *buf;
+	unsigned long virt_addr;
+
+	if (kmalloc_flag) {
+		sdev->ring = kmalloc(sdev->ring_sz, GFP_KERNEL);
+		if (sdev->ring == NULL) {
+			pr_err("kmalloc failed, ring_sz= %d\n", sdev->ring_sz);
+			return -ENOMEM;
+		}
+
+		buf = (char *)sdev->ring;
+
+		/*reserve kmalloc memory as pages to make them remapable*/
+		for (virt_addr = (unsigned long)buf;
+				virt_addr < (unsigned long)buf + sdev->ring_sz;
+				virt_addr += PAGE_SIZE) {
+			SetPageReserved(virt_to_page((virt_addr)));
+		}
+	} else {
+		sdev->ring = vmalloc(sdev->ring_sz);
+		if (sdev->ring == NULL) {
+			pr_err("vmalloc failed, ring_sz = %d\n", sdev->ring_sz);
+			return -ENOMEM;
+		}
+		buf = (char *)sdev->ring;
+
+		/*reserve vmalloc memory as pages to make them remapable*/
+		for (virt_addr = (unsigned long)buf;
+				virt_addr < (unsigned long)buf + sdev->ring_sz;
+				virt_addr += PAGE_SIZE) {
+			SetPageReserved(vmalloc_to_page(
+				(unsigned long *) virt_addr));
+		}
+	}
+
+	memset(sdev->ring, 0, sdev->ring_sz);
+
+	sdev->num_tot_blks = (sdev->ring_sz / BLK_SIZE);
+	sdev->num_writers = 0;
+	sdev->write_idx = 0;
+	sdev->read_idx = 0;
+
+	sdev->num_write_avail_blks = sdev->num_tot_blks;
+	/*no. of blocks available for write*/
+	sdev->num_write_in_prog_blks = 0;
+	/*no. of blocks held by writers to perform writes*/
+
+	sdev->num_read_avail_blks = 0;
+	/*no. of blocks ready for read*/
+	sdev->num_read_in_prog_blks = 0;
+	/*no. of blocks held by the reader to perform read*/
+
+	return 0;
+}
+
+void ringbuf_cleanup(struct seemp_logk_dev *sdev)
+{
+	unsigned long virt_addr;
+
+	if (kmalloc_flag) {
+		for (virt_addr = (unsigned long)sdev->ring;
+			virt_addr < (unsigned long)sdev->ring + sdev->ring_sz;
+			virt_addr += PAGE_SIZE) {
+			/*clear all pages*/
+			ClearPageReserved(virt_to_page((unsigned long *)
+				virt_addr));
+		}
+		kfree(sdev->ring);
+	} else {
+		for (virt_addr = (unsigned long)sdev->ring;
+			virt_addr < (unsigned long)sdev->ring + sdev->ring_sz;
+			virt_addr += PAGE_SIZE) {
+			/*clear all pages*/
+			ClearPageReserved(vmalloc_to_page((unsigned long *)
+				virt_addr));
+		}
+		vfree(sdev->ring);
+	}
+}
+
+struct seemp_logk_blk *ringbuf_fetch_wr_block
+					(struct seemp_logk_dev *sdev)
+{
+	struct seemp_logk_blk *blk = NULL;
+	int idx;
+
+	mutex_lock(&sdev->lock);
+	if (sdev->num_write_avail_blks == 0) {
+		idx = -1;
+		mutex_unlock(&sdev->lock);
+		return blk;
+	}
+
+	idx = sdev->write_idx;
+	sdev->write_idx = (sdev->write_idx + 1) % sdev->num_tot_blks;
+	sdev->num_write_avail_blks--;
+	sdev->num_write_in_prog_blks++;
+	sdev->num_writers++;
+
+	blk = &sdev->ring[idx];
+	blk->status = 0x0;
+
+	mutex_unlock(&sdev->lock);
+	return blk;
+}
+
+void ringbuf_finish_writer(struct seemp_logk_dev *sdev,
+				struct seemp_logk_blk *blk)
+{
+	/* Encode seemp parameters in multi-threaded mode (before mutex lock) */
+	encode_seemp_params(blk);
+
+	/*
+	 * finish writing...
+	 * the calling process will no longer access this block.
+	 */
+	mutex_lock(&sdev->lock);
+
+	sdev->num_writers--;
+	sdev->num_write_in_prog_blks--;
+	sdev->num_read_avail_blks++;
+
+	/*wake up any readers*/
+	if (sdev->num_writers == 0)
+		wake_up_interruptible(&sdev->readers_wq);
+
+	mutex_unlock(&sdev->lock);
+}
+
+int ringbuf_count_marked(struct seemp_logk_dev *sdev)
+{
+	int i;
+	unsigned int marked;
+
+	mutex_lock(&sdev->lock);
+	for (marked = 0, i = 0; i < sdev->num_tot_blks; i++)
+		if (sdev->ring[i].status & 0x1)
+			marked++;
+	mutex_unlock(&sdev->lock);
+
+	return marked;
+}
diff --git a/drivers/platform/msm/seemp_core/seemp_ringbuf.h b/drivers/platform/msm/seemp_core/seemp_ringbuf.h
new file mode 100644
index 0000000..3abdf77
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_ringbuf.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014-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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SEEMP_RINGBUF_H__
+#define __SEEMP_RINGBUF_H__
+
+/*
+ * This header exports pingpong's API
+ */
+
+int ringbuf_init(struct seemp_logk_dev *sdev);
+struct seemp_logk_blk *ringbuf_fetch_wr_block
+(struct seemp_logk_dev *sdev);
+void ringbuf_finish_writer(struct seemp_logk_dev *sdev,
+				struct seemp_logk_blk *blk);
+void ringbuf_cleanup(struct seemp_logk_dev *sdev);
+int ringbuf_count_marked(struct seemp_logk_dev *sdev);
+
+#endif
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
index c977d1b..bf5a526 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
@@ -24,6 +24,9 @@
 #define NUM_LNODES	3
 #define MAX_STR_CL	50
 
+#define MSM_BUS_MAS_ALC	144
+#define MSM_BUS_RSC_APPS 8000
+
 struct bus_search_type {
 	struct list_head link;
 	struct list_head node_list;
@@ -38,6 +41,7 @@
 static LIST_HEAD(input_list);
 static LIST_HEAD(apply_list);
 static LIST_HEAD(commit_list);
+static LIST_HEAD(late_init_clist);
 static LIST_HEAD(query_list);
 
 DEFINE_RT_MUTEX(msm_bus_adhoc_lock);
@@ -123,6 +127,9 @@
 		goto exit_bcm_add_bus_req;
 	}
 
+	if (cur_dev->node_info->bcm_req_idx != -1)
+		goto exit_bcm_add_bus_req;
+
 	if (!cur_dev->node_info->num_bcm_devs)
 		goto exit_bcm_add_bus_req;
 
@@ -179,8 +186,6 @@
 		cur_dev->node_info->bcm_req_idx = lnode_idx;
 		memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX);
 		memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX);
-		MSM_BUS_ERR("%s: Added %d entry to bcm %d @ %d\n", __func__,
-			lnode->bus_dev_id, bcm_dev->node_info->id, lnode_idx);
 	}
 
 exit_bcm_add_bus_req:
@@ -316,7 +321,6 @@
 		MSM_BUS_ERR("%s: Can't find dest dev %d", __func__, dest);
 		goto exit_prune_path;
 	}
-	MSM_BUS_ERR("%s: dest dev %d", __func__, dest);
 
 	lnode_hop = gen_lnode(dest_dev, search_dev_id, lnode_hop, cl_name);
 	bcm_add_bus_req(dest_dev);
@@ -520,7 +524,6 @@
 				max_ib = max(max_ib,
 				max(bcm_dev->lnode_list[i].lnode_ib[ACTIVE_CTX],
 				bcm_dev->lnode_list[i].lnode_ib[DUAL_CTX]));
-
 				max_ab = max(max_ab,
 				bcm_dev->lnode_list[i].lnode_ab[ACTIVE_CTX] +
 				bcm_dev->lnode_list[i].lnode_ab[DUAL_CTX]);
@@ -531,9 +534,14 @@
 					bcm_dev->lnode_list[i].lnode_ab[ctx]);
 			}
 		}
-
 		bcm_dev->node_bw[ctx].max_ab = max_ab;
 		bcm_dev->node_bw[ctx].max_ib = max_ib;
+
+		max_ab = msm_bus_div64(max_ab, bcm_dev->bcmdev->unit_size);
+		max_ib = msm_bus_div64(max_ib, bcm_dev->bcmdev->unit_size);
+
+		bcm_dev->node_vec[ctx].vec_a = max_ab;
+		bcm_dev->node_vec[ctx].vec_b = max_ib;
 	}
 exit_bcm_update_bus_req:
 	return;
@@ -598,44 +606,81 @@
 			}
 		}
 
+		max_query_ab = msm_bus_div64(max_query_ab,
+						bcm_dev->bcmdev->unit_size);
+		max_query_ib = msm_bus_div64(max_query_ib,
+						bcm_dev->bcmdev->unit_size);
+
 		bcm_dev->node_bw[ctx].max_query_ab = max_query_ab;
 		bcm_dev->node_bw[ctx].max_query_ib = max_query_ib;
-
 	}
 exit_bcm_query_bus_req:
 	return;
 }
 
-
-
-int bcm_remove_handoff_req(struct device *dev, void *data)
+static void bcm_update_alc_req(struct msm_bus_node_device_type *dev, int ctx)
 {
 	struct msm_bus_node_device_type *bcm_dev = NULL;
 	int i;
-	uint64_t max_ib = 0;
-	uint64_t max_ab = 0;
+	uint64_t max_alc = 0;
+
+	if (!dev || !to_msm_bus_node(dev->node_info->bus_device)) {
+		MSM_BUS_ERR("Bus node pointer is Invalid");
+		goto exit_bcm_update_alc_req;
+	}
+
+	for (i = 0; i < dev->num_lnodes; i++)
+		max_alc = max(max_alc, dev->lnode_list[i].alc_idx[ctx]);
+
+	dev->node_bw[ctx].max_alc = max_alc;
+
+	bcm_dev = to_msm_bus_node(dev->node_info->bcm_devs[0]);
+
+	if (ctx == ACTIVE_CTX) {
+		max_alc = max(max_alc,
+				max(dev->node_bw[ACTIVE_CTX].max_alc,
+				dev->node_bw[DUAL_CTX].max_alc));
+	} else {
+		max_alc = dev->node_bw[ctx].max_alc;
+	}
+
+	bcm_dev->node_bw[ctx].max_alc = max_alc;
+	bcm_dev->node_vec[ctx].vec_a = max_alc;
+	bcm_dev->node_vec[ctx].vec_b = 0;
+
+exit_bcm_update_alc_req:
+	return;
+}
+
+int bcm_remove_handoff_req(struct device *dev, void *data)
+{
+	struct msm_bus_node_device_type *bus_dev = NULL;
+	struct msm_bus_node_device_type *cur_bcm = NULL;
+	struct msm_bus_node_device_type *cur_rsc = NULL;
 	int ret = 0;
 
 	rt_mutex_lock(&msm_bus_adhoc_lock);
 
-	bcm_dev = to_msm_bus_node(dev);
-	if (!bcm_dev) {
-		MSM_BUS_ERR("%s: Null device ptr", __func__);
-		goto exit_bcm_remove_handoff_req;
-	}
-
-	if (!bcm_dev->node_info->is_bcm_dev)
+	bus_dev = to_msm_bus_node(dev);
+	if (bus_dev->node_info->is_bcm_dev ||
+		bus_dev->node_info->is_fab_dev ||
+		bus_dev->node_info->is_rsc_dev)
 		goto exit_bcm_remove_handoff_req;
 
-	for (i = 0; i < bcm_dev->num_lnodes; i++) {
-		max_ib = max(max_ib,
-				bcm_dev->lnode_list[i].lnode_ib[0]);
-		max_ab = max(max_ab,
-				bcm_dev->lnode_list[i].lnode_ab[0]);
+	if (bus_dev->node_info->num_bcm_devs) {
+		cur_bcm = to_msm_bus_node(bus_dev->node_info->bcm_devs[0]);
+		if (cur_bcm->node_info->num_rsc_devs) {
+			cur_rsc =
+			to_msm_bus_node(cur_bcm->node_info->rsc_devs[0]);
+			if (cur_rsc->node_info->id != MSM_BUS_RSC_APPS)
+				goto exit_bcm_remove_handoff_req;
+		}
 	}
 
-	bcm_dev->node_bw[0].max_ab = max_ab;
-	bcm_dev->node_bw[0].max_ib = max_ib;
+	if (!bus_dev->dirty) {
+		list_add_tail(&bus_dev->link, &late_init_clist);
+		bus_dev->dirty = true;
+	}
 
 exit_bcm_remove_handoff_req:
 	rt_mutex_unlock(&msm_bus_adhoc_lock);
@@ -684,7 +729,6 @@
 		sum_ab += bus_dev->lnode_list[i].lnode_query_ab[ctx];
 	}
 
-	MSM_BUS_ERR("aggregate: query_ab:%llu\n", sum_ab);
 	bus_dev->node_bw[ctx].sum_query_ab = sum_ab;
 	bus_dev->node_bw[ctx].max_query_ib = max_ib;
 
@@ -766,6 +810,18 @@
 	INIT_LIST_HEAD(&commit_list);
 }
 
+void commit_late_init_data(void)
+{
+	rt_mutex_lock(&msm_bus_adhoc_lock);
+
+	msm_bus_commit_data(&late_init_clist);
+	INIT_LIST_HEAD(&late_init_clist);
+
+	rt_mutex_unlock(&msm_bus_adhoc_lock);
+}
+
+
+
 static void add_node_to_clist(struct msm_bus_node_device_type *node)
 {
 	struct msm_bus_node_device_type *node_parent =
@@ -870,6 +926,63 @@
 	return ret;
 }
 
+static int update_alc_vote(struct device *alc_dev, uint64_t act_req_fa_lat,
+			uint64_t act_req_idle_time, uint64_t slp_req_fa_lat,
+			uint64_t slp_req_idle_time, uint64_t cur_fa_lat,
+			uint64_t cur_idle_time, int idx, int ctx)
+{
+	struct link_node *lnode = NULL;
+	struct msm_bus_node_device_type *dev_info = NULL;
+	int curr_idx, i;
+	int ret = 0;
+
+	if (IS_ERR_OR_NULL(alc_dev)) {
+		MSM_BUS_ERR("%s: No source device", __func__);
+		ret = -ENODEV;
+		goto exit_update_alc_vote;
+	}
+
+	if (idx < 0) {
+		MSM_BUS_ERR("%s: Invalid lnode idx %d", __func__, idx);
+		ret = -ENXIO;
+		goto exit_update_alc_vote;
+	}
+
+	dev_info = to_msm_bus_node(alc_dev);
+	curr_idx = idx;
+
+	if (curr_idx >= dev_info->num_lnodes) {
+		MSM_BUS_ERR("%s: Invalid lnode Idx %d num lnodes %d",
+				 __func__, curr_idx, dev_info->num_lnodes);
+		ret = -ENXIO;
+		goto exit_update_alc_vote;
+	}
+
+	lnode = &dev_info->lnode_list[curr_idx];
+	if (!lnode) {
+		MSM_BUS_ERR("%s: Invalid lnode ptr lnode %d",
+			 __func__, curr_idx);
+		ret = -ENXIO;
+		goto exit_update_alc_vote;
+	}
+
+	/*
+	 * Add aggregation and mapping logic once LUT is avail.
+	 * Use default values for time being.
+	 */
+	lnode->alc_idx[ACTIVE_CTX] = 12;
+	lnode->alc_idx[DUAL_CTX] = 0;
+
+	for (i = 0; i < NUM_CTX; i++)
+		bcm_update_alc_req(dev_info, i);
+
+	add_node_to_clist(dev_info);
+
+exit_update_alc_vote:
+	return ret;
+}
+
+
 static int query_path(struct device *src_dev, int dest, uint64_t act_req_ib,
 			uint64_t act_req_bw, uint64_t slp_req_ib,
 			uint64_t slp_req_bw, uint64_t cur_ib, uint64_t cur_bw,
@@ -1160,6 +1273,40 @@
 	}
 	client->pdata = pdata;
 
+	if (pdata->alc) {
+		client->curr = -1;
+		lnode = kzalloc(sizeof(int), GFP_KERNEL);
+
+		if (ZERO_OR_NULL_PTR(lnode)) {
+			MSM_BUS_ERR("%s: Error allocating lnode!", __func__);
+			goto exit_lnode_malloc_fail;
+		}
+		client->src_pnode = lnode;
+
+		client->src_devs = kzalloc(sizeof(struct device *),
+							GFP_KERNEL);
+		if (IS_ERR_OR_NULL(client->src_devs)) {
+			MSM_BUS_ERR("%s: Error allocating src_dev!", __func__);
+			goto exit_src_dev_malloc_fail;
+		}
+		src = MSM_BUS_MAS_ALC;
+		dev = bus_find_device(&msm_bus_type, NULL,
+				(void *) &src,
+				msm_bus_device_match_adhoc);
+		if (IS_ERR_OR_NULL(dev)) {
+			MSM_BUS_ERR("%s:Failed to find alc device",
+				__func__);
+			goto exit_invalid_data;
+		}
+		gen_lnode(dev, MSM_BUS_MAS_ALC, 0, pdata->name);
+		bcm_add_bus_req(dev);
+
+		client->src_devs[0] = dev;
+
+		handle = gen_handle(client);
+		goto exit_register_client;
+	}
+
 	lnode = kcalloc(pdata->usecase->num_paths, sizeof(int), GFP_KERNEL);
 	if (ZERO_OR_NULL_PTR(lnode)) {
 		MSM_BUS_ERR("%s: Error allocating pathnode ptr!", __func__);
@@ -1293,6 +1440,58 @@
 	return ret;
 }
 
+static int update_client_alc(struct msm_bus_client *client, bool log_trns,
+							unsigned int idx)
+{
+	int lnode, cur_idx;
+	uint64_t req_idle_time, req_fal, dual_idle_time, dual_fal,
+	cur_idle_time, cur_fal;
+	int ret = 0;
+	struct msm_bus_scale_pdata *pdata;
+	struct device *src_dev;
+
+	if (!client) {
+		MSM_BUS_ERR("Client handle  Null");
+		ret = -ENXIO;
+		goto exit_update_client_alc;
+	}
+
+	pdata = client->pdata;
+	if (!pdata) {
+		MSM_BUS_ERR("Client pdata Null");
+		ret = -ENXIO;
+		goto exit_update_client_alc;
+	}
+
+	cur_idx = client->curr;
+	client->curr = idx;
+	req_fal = pdata->usecase_lat[idx].fal_ns;
+	req_idle_time = pdata->usecase_lat[idx].idle_t_ns;
+	lnode = client->src_pnode[0];
+	src_dev = client->src_devs[0];
+
+	if (pdata->active_only) {
+		dual_fal = 0;
+		dual_idle_time = 0;
+	} else {
+		dual_fal = req_fal;
+		dual_idle_time = req_idle_time;
+	}
+
+	ret = update_alc_vote(src_dev, req_fal, req_idle_time, dual_fal,
+		dual_idle_time, cur_fal, cur_idle_time, lnode,
+		pdata->active_only);
+
+	if (ret) {
+		MSM_BUS_ERR("%s: Update path failed! %d ctx %d\n",
+				__func__, ret, pdata->active_only);
+		goto exit_update_client_alc;
+	}
+	commit_data();
+exit_update_client_alc:
+	return ret;
+}
+
 static int query_usecase(struct msm_bus_client *client, bool log_trns,
 					unsigned int idx,
 					struct msm_bus_tcs_usecase *tcs_usecase)
@@ -1483,8 +1682,13 @@
 
 	MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__,
 		cl, index, client->curr, client->pdata->usecase->num_paths);
-	msm_bus_dbg_client_data(client->pdata, index, cl);
-	ret = update_client_paths(client, log_transaction, index);
+
+	if (pdata->alc)
+		ret = update_client_alc(client, log_transaction, index);
+	else {
+		msm_bus_dbg_client_data(client->pdata, index, cl);
+		ret = update_client_paths(client, log_transaction, index);
+	}
 	if (ret) {
 		pr_err("%s: Err updating path\n", __func__);
 		goto exit_update_request;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_dbg.c b/drivers/soc/qcom/msm_bus/msm_bus_dbg.c
index 5908122..015edb3 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_dbg.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, 2014-2016, The Linux Foundation. All rights
+/* Copyright (c) 2010-2012, 2014-2017, The Linux Foundation. All rights
  * reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -439,7 +439,6 @@
 
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->clid == clid) {
-			debugfs_remove(cldata->file);
 			list_del(&cldata->list);
 			kfree(cldata);
 			break;
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 beb5c2b..4167480 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -45,6 +45,7 @@
 
 static struct list_head bcm_query_list_inorder[VCD_MAX_CNT];
 static struct msm_bus_node_device_type *cur_rsc;
+static bool init_time = true;
 
 struct bcm_db {
 	uint32_t unit_size;
@@ -265,27 +266,23 @@
 }
 
 static int tcs_cmd_gen(struct msm_bus_node_device_type *cur_bcm,
-				struct tcs_cmd *cmd, uint64_t ib,
-					uint64_t ab, bool commit)
+				struct tcs_cmd *cmd, uint64_t vec_a,
+					uint64_t vec_b, bool commit)
 {
 	int ret = 0;
 	bool valid = true;
 
-	if (ib == 0 && ab == 0) {
+	if (vec_a == 0 && vec_b == 0)
 		valid = false;
-	} else {
-		do_div(ib, cur_bcm->bcmdev->unit_size);
-		do_div(ab, cur_bcm->bcmdev->unit_size);
-	}
 
-	if (ib > BCM_TCS_CMD_VOTE_MASK)
-		ib = BCM_TCS_CMD_VOTE_MASK;
+	if (vec_a > BCM_TCS_CMD_VOTE_MASK)
+		vec_a = BCM_TCS_CMD_VOTE_MASK;
 
-	if (ab > BCM_TCS_CMD_VOTE_MASK)
-		ab = BCM_TCS_CMD_VOTE_MASK;
+	if (vec_b > BCM_TCS_CMD_VOTE_MASK)
+		vec_b = BCM_TCS_CMD_VOTE_MASK;
 
 	cmd->addr = cur_bcm->bcmdev->addr;
-	cmd->data = BCM_TCS_CMD(commit, valid, ab, ib);
+	cmd->data = BCM_TCS_CMD(commit, valid, vec_a, vec_b);
 	cmd->complete = commit;
 
 	return ret;
@@ -333,8 +330,8 @@
 				idx++;
 			}
 			tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
-				cur_bcm->node_bw[ACTIVE_CTX].max_ib,
-				cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit);
+				cur_bcm->node_vec[ACTIVE_CTX].vec_a,
+				cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
 			k++;
 			last_tcs = k;
 			cur_bcm->updated = true;
@@ -352,10 +349,10 @@
 			continue;
 		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
 			commit = false;
-			if ((cur_bcm->node_bw[DUAL_CTX].max_ab ==
-				cur_bcm->node_bw[ACTIVE_CTX].max_ab) &&
-				(cur_bcm->node_bw[DUAL_CTX].max_ib ==
-				cur_bcm->node_bw[ACTIVE_CTX].max_ib)) {
+			if ((cur_bcm->node_vec[DUAL_CTX].vec_a ==
+				cur_bcm->node_vec[ACTIVE_CTX].vec_a) &&
+				(cur_bcm->node_vec[DUAL_CTX].vec_b ==
+				cur_bcm->node_vec[ACTIVE_CTX].vec_b)) {
 				if (last_tcs != -1 &&
 					list_is_last(&cur_bcm->link,
 					&cur_bcm_clist[i])) {
@@ -378,11 +375,11 @@
 			}
 
 			tcs_cmd_gen(cur_bcm, &cmdlist_wake[k],
-				cur_bcm->node_bw[ACTIVE_CTX].max_ib,
-				cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit);
+				cur_bcm->node_vec[ACTIVE_CTX].vec_a,
+				cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
 			tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k],
-				cur_bcm->node_bw[DUAL_CTX].max_ib,
-				cur_bcm->node_bw[DUAL_CTX].max_ab, commit);
+				cur_bcm->node_vec[DUAL_CTX].vec_a,
+				cur_bcm->node_vec[DUAL_CTX].vec_b, commit);
 			k++;
 		}
 	}
@@ -485,10 +482,11 @@
 
 	cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);
 
-	if (cur_bcm->node_bw[DUAL_CTX].max_ab == 0 &&
-			cur_bcm->node_bw[ACTIVE_CTX].max_ab == 0 &&
-			cur_bcm->node_bw[DUAL_CTX].max_ib == 0 &&
-			cur_bcm->node_bw[ACTIVE_CTX].max_ib == 0) {
+	if (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 == false) {
 		cur_bcm->dirty = false;
 		list_del_init(&cur_bcm->link);
 	}
@@ -550,25 +548,31 @@
 		if (list_empty(&cur_bcm_clist[i]))
 			continue;
 		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
-			if ((cur_bcm->node_bw[DUAL_CTX].max_ab !=
-				cur_bcm->node_bw[ACTIVE_CTX].max_ab) ||
-				(cur_bcm->node_bw[DUAL_CTX].max_ib !=
-				cur_bcm->node_bw[ACTIVE_CTX].max_ib)) {
+			if ((cur_bcm->node_vec[DUAL_CTX].vec_a !=
+				cur_bcm->node_vec[ACTIVE_CTX].vec_a) ||
+				(cur_bcm->node_vec[DUAL_CTX].vec_b !=
+				cur_bcm->node_vec[ACTIVE_CTX].vec_b)) {
 				cnt_sleep++;
 				cnt_wake++;
 			}
-			if (!cur_bcm->updated)
-				cnt_active++;
+			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))
+				continue;
+			cnt_active++;
 		}
 		cnt_vcd++;
 	}
 
-	MSM_BUS_ERR("%s: cmd_gen\n", __func__);
 	n_active = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
 	n_wake = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
 	n_sleep = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
 
-	cmdlist_active = kcalloc(cnt_active, sizeof(struct tcs_cmd),
+	if (cnt_active)
+		cmdlist_active = kcalloc(cnt_active, sizeof(struct tcs_cmd),
 								GFP_KERNEL);
 	if (cnt_sleep && cnt_wake) {
 		cmdlist_wake = kcalloc(cnt_wake, sizeof(struct tcs_cmd),
@@ -1086,6 +1090,7 @@
 
 	node_info->name = pdata_node_info->name;
 	node_info->id =  pdata_node_info->id;
+	node_info->bcm_req_idx = -1;
 	node_info->bus_device_id = pdata_node_info->bus_device_id;
 	node_info->mas_rpm_id = pdata_node_info->mas_rpm_id;
 	node_info->slv_rpm_id = pdata_node_info->slv_rpm_id;
@@ -1289,6 +1294,7 @@
 
 	bus_node->node_info = node_info;
 	bus_node->ap_owned = pdata->ap_owned;
+	bus_node->dirty = false;
 	bus_dev->of_node = pdata->of_node;
 
 	if (msm_bus_copy_node_info(pdata, bus_dev) < 0) {
@@ -1653,9 +1659,11 @@
 	int rc;
 
 	MSM_BUS_ERR("msm_bus_late_init: Remove handoff bw requests\n");
+	init_time = false;
 	rc = bus_for_each_dev(&msm_bus_type, NULL, NULL,
 						bcm_remove_handoff_req);
 
+	commit_late_init_data();
 	return rc;
 }
 subsys_initcall(msm_bus_device_init_driver);
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of.c b/drivers/soc/qcom/msm_bus/msm_bus_of.c
index 856dcce..fd72ae6 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_of.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_of.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -46,6 +46,7 @@
 {
 	struct msm_bus_scale_pdata *pdata = NULL;
 	struct msm_bus_paths *usecase = NULL;
+	struct msm_bus_lat_vectors *usecase_lat = NULL;
 	int i = 0, j, ret, num_usecases = 0, num_paths, len;
 	const uint32_t *vec_arr = NULL;
 	bool mem_err = false;
@@ -85,6 +86,42 @@
 		pr_debug("Using dual context by default\n");
 	}
 
+	pdata->alc = of_property_read_bool(of_node, "qcom,msm-bus,alc-voter");
+
+	if (pdata->alc) {
+		usecase_lat = devm_kzalloc(&pdev->dev,
+				(sizeof(struct msm_bus_lat_vectors) *
+				pdata->num_usecases), GFP_KERNEL);
+		if (!usecase_lat) {
+			mem_err = true;
+			goto err;
+		}
+
+		vec_arr = of_get_property(of_node,
+					"qcom,msm-bus,vectors-alc", &len);
+		if (vec_arr == NULL) {
+			pr_err("Error: Lat vector array not found\n");
+			goto err;
+		}
+
+		if (len != num_usecases * sizeof(uint32_t) * 2) {
+			pr_err("Error: Length-error on getting vectors\n");
+			goto err;
+		}
+
+		for (i = 0; i < num_usecases; i++) {
+			int index = i * 2;
+
+			usecase_lat[i].fal_ns = (uint64_t)
+				KBTOB(be32_to_cpu(vec_arr[index]));
+			usecase_lat[i].idle_t_ns = (uint64_t)
+				KBTOB(be32_to_cpu(vec_arr[index + 1]));
+		}
+
+		pdata->usecase_lat = usecase_lat;
+		return pdata;
+	}
+
 	usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) *
 		pdata->num_usecases), GFP_KERNEL);
 	if (!usecase) {
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
index f415735..fad7afa 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
@@ -29,6 +29,7 @@
 	uint64_t lnode_ab[NUM_CTX];
 	uint64_t lnode_query_ib[NUM_CTX];
 	uint64_t lnode_query_ab[NUM_CTX];
+	uint64_t alc_idx[NUM_CTX];
 	int next;
 	struct device *next_dev;
 	struct list_head link;
@@ -61,11 +62,17 @@
 	uint64_t sum_query_ab;
 	uint64_t max_query_ib;
 	uint64_t max_query_ab;
+	uint64_t max_alc;
 	uint64_t cur_clk_hz;
 	uint32_t util_used;
 	uint32_t vrail_used;
 };
 
+struct nodevector {
+	uint64_t vec_a;
+	uint64_t vec_b;
+};
+
 struct msm_bus_rsc_device_type {
 	struct rpmh_client *mbox;
 	struct list_head bcm_clist[VCD_MAX_CNT];
@@ -167,6 +174,7 @@
 	int num_lnodes;
 	struct link_node *lnode_list;
 	struct nodebw node_bw[NUM_CTX];
+	struct nodevector node_vec[NUM_CTX];
 	struct list_head link;
 	struct list_head query_link;
 	struct nodeclk clk[NUM_CTX];
@@ -193,6 +201,7 @@
 				int throttle_en, uint64_t lim_bw);
 int msm_bus_commit_data(struct list_head *clist);
 int bcm_remove_handoff_req(struct device *dev, void *data);
+void commit_late_init_data(void);
 int msm_bus_query_gen(struct list_head *qlist,
 				struct msm_bus_tcs_usecase *tcs_usecase);
 void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size,
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index aeecf29..1635bab 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -37,14 +37,13 @@
 		.msg = { 0 },			\
 		.msg.state = s,			\
 		.msg.is_complete = true,	\
-		.msg.payload = &name.cmd,	\
-		.msg.num_payload = 1,		\
-		.cmd = { 0 },			\
+		.msg.payload = name.cmd,	\
+		.msg.num_payload = 0,		\
+		.cmd = { { 0 } },		\
 		.waitq = q,			\
 		.wait_count = c,		\
 		.rc = rc,			\
 		.bit = -1,			\
-		.free_cmd = NULL,		\
 	}
 
 struct rpmh_req {
@@ -56,13 +55,11 @@
 
 struct rpmh_msg {
 	struct tcs_mbox_msg msg;
-	/* A single command for our use here */
-	struct tcs_cmd cmd;
+	struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
 	wait_queue_head_t *waitq;
 	atomic_t *wait_count;
 	struct rpmh_client *rc;
 	int bit;
-	void *free_cmd;
 	int err; /* relay error from mbox for sync calls */
 };
 
@@ -120,7 +117,6 @@
 	struct rpmh_mbox *rpm = rpm_msg->rc->rpmh;
 	atomic_t *wc = rpm_msg->wait_count;
 	wait_queue_head_t *waitq = rpm_msg->waitq;
-	void *free = rpm_msg->free_cmd;
 
 	rpm_msg->err = r;
 
@@ -139,7 +135,7 @@
 	/*
 	 * Copy the child object pointers before freeing up the parent,
 	 * This way even if the parent (rpm_msg) object gets reused, we
-	 * can free up the child objects (free_cmd and wq/wc) parallely.
+	 * can free up the child objects (wq/wc) parallely.
 	 * If you free up the children before the parent, then we run
 	 * into an issue that the stack allocated parent object may be
 	 * invalid before we can check the ->bit value.
@@ -152,9 +148,6 @@
 		spin_unlock(&rpm->lock);
 	}
 
-	/* Nobody should be needing the request anymore */
-	kfree(free);
-
 	/* Signal the blocking thread we are done */
 	if (waitq) {
 		atomic_dec(wc);
@@ -254,6 +247,9 @@
 		ret = mbox_send_message(rc->chan, &rpm_msg->msg);
 		if (ret > 0)
 			ret = 0;
+	} else {
+		/* Clean up our call by spoofing tx_done */
+		rpmh_tx_done(&rc->client, &rpm_msg->msg, ret);
 	}
 
 	return ret;
@@ -285,10 +281,10 @@
 	if (!rpm_msg)
 		return -ENOMEM;
 
-	rpm_msg->cmd.addr = addr;
-	rpm_msg->cmd.data = data;
+	rpm_msg->cmd[0].addr = addr;
+	rpm_msg->cmd[0].data = data;
 
-	rpm_msg->msg.payload = &rpm_msg->cmd;
+	rpm_msg->msg.payload = rpm_msg->cmd;
 	rpm_msg->msg.num_payload = 1;
 
 	return __rpmh_write(rc, state, rpm_msg);
@@ -325,8 +321,9 @@
 	if (rpmh_standalone)
 		return 0;
 
-	rpm_msg.cmd.addr = addr;
-	rpm_msg.cmd.data = data;
+	rpm_msg.cmd[0].addr = addr;
+	rpm_msg.cmd[0].data = data;
+	rpm_msg.msg.num_payload = 1;
 
 	ret = __rpmh_write(rc, state, &rpm_msg);
 	if (ret < 0)
@@ -341,29 +338,22 @@
 EXPORT_SYMBOL(rpmh_write_single);
 
 struct rpmh_msg *__get_rpmh_msg_async(struct rpmh_client *rc,
-	enum rpmh_state state, struct tcs_cmd *cmd, int n, bool fast)
+		enum rpmh_state state, struct tcs_cmd *cmd, int n)
 {
 	struct rpmh_msg *rpm_msg;
-	struct tcs_cmd *tcs_cmd;
 
 	if (IS_ERR_OR_NULL(rc) || !cmd || n <= 0 || n > MAX_RPMH_PAYLOAD)
 		return ERR_PTR(-EINVAL);
 
-	tcs_cmd = kcalloc(n, sizeof(*cmd), fast ? GFP_ATOMIC : GFP_KERNEL);
-	if (!tcs_cmd)
-		return ERR_PTR(-ENOMEM);
-	memcpy(tcs_cmd, cmd, n * sizeof(*tcs_cmd));
-
 	rpm_msg = get_msg_from_pool(rc);
-	if (!rpm_msg) {
-		kfree(tcs_cmd);
+	if (!rpm_msg)
 		return ERR_PTR(-ENOMEM);
-	}
+
+	memcpy(rpm_msg->cmd, cmd, n * sizeof(*cmd));
 
 	rpm_msg->msg.state = state;
-	rpm_msg->msg.payload = tcs_cmd;
+	rpm_msg->msg.payload = rpm_msg->cmd;
 	rpm_msg->msg.num_payload = n;
-	rpm_msg->free_cmd = tcs_cmd;
 
 	return rpm_msg;
 }
@@ -389,8 +379,7 @@
 	if (rpmh_standalone)
 		return 0;
 
-	rpm_msg = __get_rpmh_msg_async(rc, state, cmd, n, true);
-
+	rpm_msg = __get_rpmh_msg_async(rc, state, cmd, n);
 	if (IS_ERR(rpm_msg))
 		return PTR_ERR(rpm_msg);
 
@@ -430,7 +419,7 @@
 	if (rpmh_standalone)
 		return 0;
 
-	rpm_msg.msg.payload = cmd;
+	memcpy(rpm_msg.cmd, cmd, n * sizeof(*cmd));
 	rpm_msg.msg.num_payload = n;
 
 	ret = __rpmh_write(rc, state, &rpm_msg);
@@ -502,7 +491,7 @@
 
 	/* Create async request batches */
 	for (i = 0; i < count; i++) {
-		rpm_msg[i] = __get_rpmh_msg_async(rc, state, cmd, n[i], false);
+		rpm_msg[i] = __get_rpmh_msg_async(rc, state, cmd, n[i]);
 		if (IS_ERR_OR_NULL(rpm_msg[i]))
 			return PTR_ERR(rpm_msg[i]);
 		rpm_msg[i]->waitq = &waitq;
@@ -551,15 +540,16 @@
 {
 	DEFINE_RPMH_MSG_ONSTACK(rc, 0, NULL, NULL, rpm_msg);
 
-	if (IS_ERR_OR_NULL(rc))
+	if (IS_ERR_OR_NULL(rc) ||  n > MAX_RPMH_PAYLOAD)
 		return -EINVAL;
 
 	if (rpmh_standalone)
 		return 0;
 
-	rpm_msg.msg.payload = cmd;
+	memcpy(rpm_msg.cmd, cmd, n * sizeof(*cmd));
 	rpm_msg.msg.num_payload = n;
 	rpm_msg.msg.is_control = true;
+	rpm_msg.msg.is_complete = false;
 
 	return mbox_send_controller_data(rc->chan, &rpm_msg.msg);
 }
@@ -587,6 +577,7 @@
 
 	rpm = rc->rpmh;
 	rpm_msg.msg.invalidate = true;
+	rpm_msg.msg.is_complete = false;
 
 	spin_lock(&rpm->lock);
 	rpm->dirty = true;
@@ -621,8 +612,9 @@
 	if (rpmh_standalone)
 		return 0;
 
-	rpm_msg.cmd.addr = addr;
-	rpm_msg.cmd.data = 0;
+	rpm_msg.cmd[0].addr = addr;
+	rpm_msg.cmd[0].data = 0;
+	rpm_msg.msg.num_payload = 1;
 
 	rpm_msg.msg.is_read = true;
 
@@ -636,7 +628,7 @@
 		return ret;
 
 	/* Read the data back from the tcs_mbox_msg structrure */
-	*resp = rpm_msg.cmd.data;
+	*resp = rpm_msg.cmd[0].data;
 
 	return rpm_msg.err;
 }
@@ -655,8 +647,10 @@
 
 	/* Wake sets are always complete and sleep sets are not */
 	rpm_msg.msg.is_complete = (state == RPMH_WAKE_ONLY_STATE);
-	rpm_msg.cmd.addr = addr;
-	rpm_msg.cmd.data = data;
+	rpm_msg.cmd[0].addr = addr;
+	rpm_msg.cmd[0].data = data;
+	rpm_msg.msg.num_payload = 1;
+	rpm_msg.msg.is_complete = false;
 
 	return mbox_send_controller_data(rc->chan, &rpm_msg.msg);
 }
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index b40d678..6a54048 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -24,7 +24,6 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
-#include <linux/debugfs.h>
 
 #include <soc/qcom/msm_qmi_interface.h>
 #include <soc/qcom/service-locator.h>
@@ -441,140 +440,3 @@
 	return 0;
 }
 EXPORT_SYMBOL(find_subsys);
-
-static struct pd_qmi_client_data test_data;
-
-static int servloc_test_pdr_cb(struct notifier_block *this,
-			unsigned long opcode, void *ptr)
-{
-	int i, rc = 0;
-	char subsys[QMI_SERVREG_LOC_NAME_LENGTH_V01];
-	struct pd_qmi_client_data *return_data;
-
-	return_data = (struct pd_qmi_client_data *)ptr;
-
-	if (opcode) {
-		pr_err("%s: Failed to get process domain!, opcode = %lu\n",
-			__func__, opcode);
-		return -EIO;
-	}
-
-		pr_err("Service Name: %s\tTotal Domains: %d\n",
-			return_data->service_name, return_data->total_domains);
-
-		for (i = 0; i < return_data->total_domains; i++) {
-			pr_err("Instance ID: %d\t ",
-				return_data->domain_list[i].instance_id);
-			pr_err("Domain Name: %s\n",
-				return_data->domain_list[i].name);
-			rc = find_subsys(return_data->domain_list[i].name,
-					subsys);
-		if (rc < 0)
-			pr_err("No valid subsys found for %s!\n",
-				return_data->domain_list[i].name);
-		else
-			pr_err("Subsys: %s\n", subsys);
-		}
-	return 0;
-}
-
-static struct notifier_block pdr_service_nb = {
-		.notifier_call  = servloc_test_pdr_cb,
-};
-
-static ssize_t servloc_read(struct file *filp, char __user *ubuf,
-		size_t cnt, loff_t *ppos)
-{
-	int rc = 0;
-	char *node_name = filp->private_data;
-
-	if (!strcmp(node_name, "test_servloc_get"))
-		rc = get_service_location(test_data.client_name,
-				test_data.service_name, &pdr_service_nb);
-
-	return rc;
-}
-
-static ssize_t servloc_write(struct file *fp, const char __user *buf,
-				size_t count, loff_t *unused)
-{
-	char *node_name = fp->private_data;
-
-	if (!buf)
-		return -EIO;
-	if (!strcmp(node_name, "service_name")) {
-		snprintf(test_data.service_name, sizeof(test_data.service_name),
-			"%.*s", (int) min((size_t)count - 1,
-			(sizeof(test_data.service_name) - 1)), buf);
-	} else {
-		snprintf(test_data.client_name, sizeof(test_data.client_name),
-			"%.*s", (int) min((size_t)count - 1,
-			(sizeof(test_data.client_name) - 1)), buf);
-	}
-	return count;
-}
-
-static const struct file_operations servloc_fops = {
-	.open	= simple_open,
-	.read	= servloc_read,
-	.write	= servloc_write,
-};
-
-static struct dentry *servloc_base_dir;
-static struct dentry *test_servloc_file;
-
-static int __init servloc_debugfs_init(void)
-{
-	servloc_base_dir = debugfs_create_dir("test_servloc", NULL);
-	return !servloc_base_dir ? -ENOMEM : 0;
-}
-
-static void servloc_debugfs_exit(void)
-{
-	debugfs_remove_recursive(servloc_base_dir);
-}
-
-static int servloc_debugfs_add(void)
-{
-	int rc;
-
-	if (!servloc_base_dir)
-		return -ENOMEM;
-
-	test_servloc_file = debugfs_create_file("client_name",
-				0644, servloc_base_dir,
-				"client_name", &servloc_fops);
-	rc = !test_servloc_file ? -ENOMEM : 0;
-
-	if (rc == 0) {
-		test_servloc_file = debugfs_create_file("service_name",
-				0644, servloc_base_dir,
-				"service_name", &servloc_fops);
-		rc = !test_servloc_file ? -ENOMEM : 0;
-	}
-
-	if (rc == 0) {
-		test_servloc_file = debugfs_create_file("test_servloc_get",
-				0644, servloc_base_dir,
-				"test_servloc_get", &servloc_fops);
-		rc = !test_servloc_file ? -ENOMEM : 0;
-	}
-	return rc;
-}
-
-static int __init service_locator_init(void)
-{
-	pr_debug("service_locator_status = %d\n", locator_status);
-	if (servloc_debugfs_init())
-		pr_err("Could not create test_servloc base directory!");
-	if (servloc_debugfs_add())
-		pr_err("Could not create test_servloc node entries!");
-	return 0;
-}
-
-static void __exit service_locator_exit(void)
-{
-	servloc_debugfs_exit();
-}
-module_init(service_locator_init);
-module_exit(service_locator_exit);
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index fca1c68..68592fe 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -21,7 +21,6 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/err.h>
-#include <linux/debugfs.h>
 #include <linux/uaccess.h>
 
 #include <soc/qcom/subsystem_restart.h>
@@ -104,6 +103,7 @@
 	struct work_struct svc_exit;
 	struct work_struct svc_rcv_msg;
 	struct work_struct ind_ack;
+	struct work_struct qmi_handle_free;
 	struct workqueue_struct *svc_event_wq;
 	struct qmi_handle *clnt_handle;
 	struct notifier_block notifier;
@@ -123,6 +123,18 @@
 static void root_service_service_arrive(struct work_struct *work);
 static void root_service_exit_work(struct work_struct *work);
 
+static void free_qmi_handle(struct work_struct *work)
+{
+	struct qmi_client_info *data = container_of(work,
+				struct qmi_client_info, qmi_handle_free);
+
+	mutex_lock(&qmi_client_release_lock);
+	data->service_connected = false;
+	qmi_handle_destroy(data->clnt_handle);
+	data->clnt_handle = NULL;
+	mutex_unlock(&qmi_client_release_lock);
+}
+
 static struct service_notif_info *_find_service_info(const char *service_path)
 {
 	struct service_notif_info *service_notif;
@@ -426,11 +438,7 @@
 	 * Destroy client handle and try connecting when
 	 * service comes up again.
 	 */
-	mutex_lock(&qmi_client_release_lock);
-	data->service_connected = false;
-	qmi_handle_destroy(data->clnt_handle);
-	data->clnt_handle = NULL;
-	mutex_unlock(&qmi_client_release_lock);
+	queue_work(data->svc_event_wq, &data->qmi_handle_free);
 }
 
 static void root_service_exit_work(struct work_struct *work)
@@ -486,7 +494,7 @@
 			info->subsys_state = ROOT_PD_SHUTDOWN;
 			break;
 		}
-		queue_work(info->svc_event_wq, &info->svc_exit);
+		root_service_service_exit(info, info->subsys_state);
 		break;
 	default:
 		break;
@@ -561,6 +569,7 @@
 	INIT_WORK(&qmi_data->svc_exit, root_service_exit_work);
 	INIT_WORK(&qmi_data->svc_rcv_msg, root_service_clnt_recv_msg);
 	INIT_WORK(&qmi_data->ind_ack, send_ind_ack);
+	INIT_WORK(&qmi_data->qmi_handle_free, free_qmi_handle);
 
 	*curr_state = service_notif->curr_state =
 				SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01;
@@ -742,179 +751,3 @@
 				&service_notif->service_notif_rcvr_list, nb);
 }
 EXPORT_SYMBOL(service_notif_unregister_notifier);
-
-struct service_notifier_test_data {
-	char service_path[MAX_STRING_LEN];
-	int instance_id;
-	struct notifier_block nb;
-	void *service_notif_handle;
-};
-
-static struct service_notifier_test_data test_data;
-
-static void print_service_provider_state(int notification, char *type)
-{
-	if (notification == SERVREG_NOTIF_SERVICE_STATE_DOWN_V01)
-		pr_info("%s: Service %s down!\n", type, test_data.service_path);
-	else if (notification == SERVREG_NOTIF_SERVICE_STATE_UP_V01)
-		pr_info("%s: Service %s up!\n", type, test_data.service_path);
-	else if (notification == SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01)
-		pr_info("%s: Service %s state uninit!\n", type,
-						test_data.service_path);
-	else
-		pr_info("%s: Service %s state Unknown 0x%x!\n", type,
-					test_data.service_path, notification);
-}
-
-static int nb_callback(struct notifier_block *nb,
-				  unsigned long notification,
-				  void *data)
-{
-	print_service_provider_state((int)notification, "Notification:");
-	return 0;
-}
-
-static ssize_t show_service_path(struct seq_file *f, void *unused)
-{
-	if (test_data.service_notif_handle)
-		seq_printf(f, "Service Path: %s\n", test_data.service_path);
-	else
-		seq_puts(f, "No existing notifier\n");
-	return 0;
-}
-
-
-static ssize_t set_service_notifier_register(struct file *fp,
-						const char __user *buf,
-						size_t count, loff_t *ppos)
-{
-	int curr_state = INT_MAX, rc;
-
-	if (!buf)
-		return -EIO;
-	if (test_data.service_notif_handle) {
-		service_notif_unregister_notifier(
-						test_data.service_notif_handle,
-						&test_data.nb);
-		test_data.service_notif_handle = NULL;
-		pr_info("Unregistering existing notifier for %s\n",
-							test_data.service_path);
-	}
-	rc = simple_write_to_buffer(test_data.service_path, MAX_STRING_LEN,
-							ppos, buf, count - 1);
-	if (rc != count - 1) {
-		pr_err("Unable to read data into kernel buffer\n");
-		goto err;
-	}
-	test_data.nb.notifier_call = nb_callback;
-	test_data.service_notif_handle = service_notif_register_notifier(
-					test_data.service_path,
-					test_data.instance_id, &test_data.nb,
-					&curr_state);
-	if (!IS_ERR(test_data.service_notif_handle)) {
-		pr_info("Notifier Registered for service %s\n",
-						test_data.service_path);
-		print_service_provider_state(curr_state, "Initial State");
-		return count;
-	}
-err:
-	test_data.service_notif_handle = NULL;
-	pr_err("Unable to register notifier for %s\n", test_data.service_path);
-	return -EIO;
-}
-
-static int open_service_notifier_register(struct inode *inode, struct file *f)
-{
-	return single_open(f, (void *) show_service_path,
-							inode->i_private);
-}
-
-static const struct file_operations service_notifier_register_fops = {
-	.open = open_service_notifier_register,
-	.read = seq_read,
-	.write = set_service_notifier_register,
-	.llseek = seq_lseek,
-	.release = seq_release,
-};
-
-static ssize_t show_service_notifier_id(struct seq_file *f, void *unused)
-{
-	seq_printf(f, "Service instance ID: %d\n", test_data.instance_id);
-	return 0;
-}
-
-static ssize_t set_service_notifier_id(struct file *fp,
-						const char __user *buf,
-						size_t count, loff_t *unused)
-{
-	int val, rc;
-	char kbuf[MAX_STRING_LEN];
-
-	if (count > MAX_STRING_LEN) {
-		rc = -EIO;
-		goto err;
-	}
-	rc = copy_from_user(kbuf, buf, count);
-	if (rc != 0) {
-		rc = -EFAULT;
-		goto err;
-	}
-
-	kbuf[count - 1] = '\0';
-	rc = kstrtoint(kbuf, 0, &val);
-	if (rc < 0)
-		goto err;
-
-	test_data.instance_id = val;
-	return count;
-err:
-	pr_err("Invalid input parameters: rc = %d\n", rc);
-	return rc;
-}
-
-static int open_service_notifier_id(struct inode *inode, struct file *f)
-{
-	return single_open(f, (void *) show_service_notifier_id,
-							inode->i_private);
-}
-
-static const struct file_operations service_notifier_id_fops = {
-	.open = open_service_notifier_id,
-	.read = seq_read,
-	.write = set_service_notifier_id,
-	.llseek = seq_lseek,
-	.release = seq_release,
-};
-
-static struct dentry *service_notifier_dir;
-static struct dentry *service_path_file;
-static struct dentry *service_id_file;
-
-static int __init service_notifier_init(void)
-{
-	service_notifier_dir = debugfs_create_dir("service_notifier", NULL);
-	if (service_notifier_dir) {
-		service_path_file = debugfs_create_file("service_path",
-				0644, service_notifier_dir, NULL,
-				&service_notifier_register_fops);
-		if (!service_path_file)
-			goto err;
-		service_id_file = debugfs_create_file("service_id",
-				0644, service_notifier_dir, NULL,
-				&service_notifier_id_fops);
-		if (!service_id_file)
-			goto err;
-	}
-	return 0;
-err:
-	debugfs_remove_recursive(service_notifier_dir);
-	return 0;
-}
-
-static void __exit service_notifier_exit(void)
-{
-	debugfs_remove_recursive(service_notifier_dir);
-	test_data.nb.notifier_call = nb_callback;
-}
-module_init(service_notifier_init);
-module_exit(service_notifier_exit);
diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c
index c846d26..e7c2bb2 100644
--- a/drivers/soc/qcom/subsystem_restart.c
+++ b/drivers/soc/qcom/subsystem_restart.c
@@ -28,7 +28,6 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/idr.h>
-#include <linux/debugfs.h>
 #include <linux/interrupt.h>
 #include <linux/of_gpio.h>
 #include <linux/cdev.h>
@@ -149,7 +148,6 @@
  * @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.)
  * @restart_order: order of other devices this devices restarts with
  * @crash_count: number of times the device has crashed
- * @dentry: debugfs directory for this device
  * @do_ramdump_on_put: ramdump on subsystem_put() if true
  * @err_ready: completion variable to record error ready from subsystem
  * @crashed: indicates if subsystem has crashed
@@ -171,9 +169,6 @@
 	int restart_level;
 	int crash_count;
 	struct subsys_soc_restart_order *restart_order;
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *dentry;
-#endif
 	bool do_ramdump_on_put;
 	struct cdev char_dev;
 	dev_t dev_no;
@@ -354,10 +349,11 @@
 	__ATTR_NULL,
 };
 
-static struct bus_type subsys_bus_type = {
+struct bus_type subsys_bus_type = {
 	.name		= "msm_subsys",
 	.dev_attrs	= subsys_attrs,
 };
+EXPORT_SYMBOL(subsys_bus_type);
 
 static DEFINE_IDA(subsys_ida);
 
@@ -1172,87 +1168,6 @@
 		notify_each_subsys_device(&dev, 1, SUBSYS_PROXY_UNVOTE, NULL);
 }
 
-#ifdef CONFIG_DEBUG_FS
-static ssize_t subsys_debugfs_read(struct file *filp, char __user *ubuf,
-		size_t cnt, loff_t *ppos)
-{
-	int r;
-	char buf[40];
-	struct subsys_device *subsys = filp->private_data;
-
-	r = snprintf(buf, sizeof(buf), "%d\n", subsys->count);
-	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
-}
-
-static ssize_t subsys_debugfs_write(struct file *filp,
-		const char __user *ubuf, size_t cnt, loff_t *ppos)
-{
-	struct subsys_device *subsys = filp->private_data;
-	char buf[10];
-	char *cmp;
-
-	cnt = min(cnt, sizeof(buf) - 1);
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-	buf[cnt] = '\0';
-	cmp = strstrip(buf);
-
-	if (!strcmp(cmp, "restart")) {
-		if (subsystem_restart_dev(subsys))
-			return -EIO;
-	} else if (!strcmp(cmp, "get")) {
-		if (subsystem_get(subsys->desc->name))
-			return -EIO;
-	} else if (!strcmp(cmp, "put")) {
-		subsystem_put(subsys);
-	} else {
-		return -EINVAL;
-	}
-
-	return cnt;
-}
-
-static const struct file_operations subsys_debugfs_fops = {
-	.open	= simple_open,
-	.read	= subsys_debugfs_read,
-	.write	= subsys_debugfs_write,
-};
-
-static struct dentry *subsys_base_dir;
-
-static int __init subsys_debugfs_init(void)
-{
-	subsys_base_dir = debugfs_create_dir("msm_subsys", NULL);
-	return !subsys_base_dir ? -ENOMEM : 0;
-}
-
-static void subsys_debugfs_exit(void)
-{
-	debugfs_remove_recursive(subsys_base_dir);
-}
-
-static int subsys_debugfs_add(struct subsys_device *subsys)
-{
-	if (!subsys_base_dir)
-		return -ENOMEM;
-
-	subsys->dentry = debugfs_create_file(subsys->desc->name,
-				0644, subsys_base_dir,
-				subsys, &subsys_debugfs_fops);
-	return !subsys->dentry ? -ENOMEM : 0;
-}
-
-static void subsys_debugfs_remove(struct subsys_device *subsys)
-{
-	debugfs_remove(subsys->dentry);
-}
-#else
-static int __init subsys_debugfs_init(void) { return 0; };
-static void subsys_debugfs_exit(void) { }
-static int subsys_debugfs_add(struct subsys_device *subsys) { return 0; }
-static void subsys_debugfs_remove(struct subsys_device *subsys) { }
-#endif
-
 static int subsys_device_open(struct inode *inode, struct file *file)
 {
 	struct subsys_device *device, *subsys_dev = 0;
@@ -1690,17 +1605,8 @@
 
 	mutex_init(&subsys->track.lock);
 
-	ret = subsys_debugfs_add(subsys);
-	if (ret) {
-		ida_simple_remove(&subsys_ida, subsys->id);
-		wakeup_source_trash(&subsys->ssr_wlock);
-		kfree(subsys);
-		return ERR_PTR(ret);
-	}
-
 	ret = device_register(&subsys->dev);
 	if (ret) {
-		subsys_debugfs_remove(subsys);
 		put_device(&subsys->dev);
 		return ERR_PTR(ret);
 	}
@@ -1761,7 +1667,6 @@
 	if (ofnode)
 		subsys_remove_restart_order(ofnode);
 err_register:
-	subsys_debugfs_remove(subsys);
 	device_unregister(&subsys->dev);
 	return ERR_PTR(ret);
 }
@@ -1790,7 +1695,6 @@
 		WARN_ON(subsys->count);
 		device_unregister(&subsys->dev);
 		mutex_unlock(&subsys->track.lock);
-		subsys_debugfs_remove(subsys);
 		subsys_char_device_remove(subsys);
 		sysmon_notifier_unregister(subsys->desc);
 		if (subsys->desc->edge)
@@ -1830,9 +1734,6 @@
 	ret = bus_register(&subsys_bus_type);
 	if (ret)
 		goto err_bus;
-	ret = subsys_debugfs_init();
-	if (ret)
-		goto err_debugfs;
 
 	char_class = class_create(THIS_MODULE, "subsys");
 	if (IS_ERR(char_class)) {
@@ -1851,8 +1752,6 @@
 err_soc:
 	class_destroy(char_class);
 err_class:
-	subsys_debugfs_exit();
-err_debugfs:
 	bus_unregister(&subsys_bus_type);
 err_bus:
 	destroy_workqueue(ssr_wq);
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 87b26445..9c3b6ff 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -256,6 +256,26 @@
 	geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_M_IRQ_CLEAR);
 }
 
+static void msm_geni_serial_poll_cancel_rx(struct uart_port *uport)
+{
+	int done = 0;
+	unsigned int irq_clear = S_CMD_DONE_EN;
+
+	done = msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
+							S_CMD_DONE_EN);
+	if (!done) {
+		geni_cancel_s_cmd(uport->membase);
+		irq_clear |= S_CMD_CANCEL_EN;
+		if (!msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
+							S_CMD_CANCEL_EN)) {
+			geni_abort_s_cmd(uport->membase);
+			irq_clear |= S_CMD_ABORT_EN;
+			msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
+								S_CMD_ABORT_EN);
+		}
+	}
+	geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_S_IRQ_CLEAR);
+}
 #ifdef CONFIG_CONSOLE_POLL
 static int msm_geni_serial_get_char(struct uart_port *uport)
 {
@@ -351,10 +371,15 @@
 	while (i < count) {
 		u32 chars_to_write = 0;
 		u32 avail_fifo_bytes = (port->tx_fifo_depth - port->tx_wm);
-
+		/*
+		 * If the WM bit never set, then the Tx state machine is not
+		 * in a valid state, so break, cancel/abort any existing
+		 * command. Unfortunately the current data being written is
+		 * lost.
+		 */
 		while (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
 						M_TX_FIFO_WATERMARK_EN))
-			cpu_relax();
+			break;
 		chars_to_write = min((unsigned int)(count - i),
 							avail_fifo_bytes);
 		if ((chars_to_write << 1) > avail_fifo_bytes)
@@ -485,7 +510,11 @@
 {
 	unsigned int geni_s_irq_en;
 	unsigned int geni_m_irq_en;
+	unsigned int geni_status;
 
+	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
+	if (geni_status & S_GENI_CMD_ACTIVE)
+		msm_geni_serial_poll_cancel_rx(uport);
 	geni_s_irq_en = geni_read_reg_nolog(uport->membase,
 						SE_GENI_S_IRQ_EN);
 	geni_m_irq_en = geni_read_reg_nolog(uport->membase,
@@ -1012,6 +1041,11 @@
 	if (!dev_port->port_setup)
 		msm_geni_serial_port_setup(uport);
 
+	/*
+	 * Make an unconditional cancel on the main sequencer to reset
+	 * it else we could end up in data loss scenarios.
+	 */
+	msm_geni_serial_poll_cancel_tx(uport);
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 
@@ -1088,6 +1122,11 @@
 	s_clk_cfg |= SER_CLK_EN;
 	s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
 
+	/*
+	 * Make an unconditional cancel on the main sequencer to reset
+	 * it else we could end up in data loss scenarios.
+	 */
+	msm_geni_serial_poll_cancel_tx(uport);
 	geni_serial_write_term_regs(uport, 0, tx_trans_cfg,
 		tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
 		stop_bit, rx_stale, s_clk_cfg);
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index b9edb53..a0bc61f 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -435,7 +435,7 @@
 
 	dev_dbg(dev, "xhci-plat runtime suspend\n");
 
-	return 0;
+	return xhci_suspend(xhci, true);
 }
 
 static int xhci_plat_runtime_resume(struct device *dev)
@@ -449,7 +449,7 @@
 
 	dev_dbg(dev, "xhci-plat runtime resume\n");
 
-	ret = 0;
+	ret = xhci_resume(xhci, false);
 	pm_runtime_mark_last_busy(dev);
 
 	return ret;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index e19e963..3ee2938 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -1426,6 +1426,7 @@
 	}
 
 	pd_phy_update_roles(pd->current_dr, pd->current_pr);
+	dual_role_instance_changed(pd->dual_role);
 }
 
 
@@ -2665,11 +2666,17 @@
 static int usbpd_dr_prop_writeable(struct dual_role_phy_instance *dual_role,
 		enum dual_role_property prop)
 {
+	struct usbpd *pd = dual_role_get_drvdata(dual_role);
+
 	switch (prop) {
 	case DUAL_ROLE_PROP_MODE:
+		return 1;
 	case DUAL_ROLE_PROP_DR:
 	case DUAL_ROLE_PROP_PR:
-		return 1;
+		if (pd)
+			return pd->current_state == PE_SNK_READY ||
+				pd->current_state == PE_SRC_READY;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/usb/phy/class-dual-role.c b/drivers/usb/phy/class-dual-role.c
index 51fcb54..9ef8895 100644
--- a/drivers/usb/phy/class-dual-role.c
+++ b/drivers/usb/phy/class-dual-role.c
@@ -70,15 +70,7 @@
 	return ret;
 }
 
-static void dual_role_changed_work(struct work_struct *work)
-{
-	struct dual_role_phy_instance *dual_role =
-	    container_of(work, struct dual_role_phy_instance,
-			 changed_work);
-
-	dev_dbg(&dual_role->dev, "%s\n", __func__);
-	kobject_uevent(&dual_role->dev.kobj, KOBJ_CHANGE);
-}
+static void dual_role_changed_work(struct work_struct *work);
 
 void dual_role_instance_changed(struct dual_role_phy_instance *dual_role)
 {
@@ -505,6 +497,17 @@
 	return ret;
 }
 
+static void dual_role_changed_work(struct work_struct *work)
+{
+	struct dual_role_phy_instance *dual_role =
+	    container_of(work, struct dual_role_phy_instance,
+			 changed_work);
+
+	dev_dbg(&dual_role->dev, "%s\n", __func__);
+	sysfs_update_group(&dual_role->dev.kobj, &dual_role_attr_group);
+	kobject_uevent(&dual_role->dev.kobj, KOBJ_CHANGE);
+}
+
 /******************* Module Init ***********************************/
 
 static int __init dual_role_class_init(void)
diff --git a/include/dt-bindings/msm/msm-bus-ids.h b/include/dt-bindings/msm/msm-bus-ids.h
index 8135da9..be2210c 100644
--- a/include/dt-bindings/msm/msm-bus-ids.h
+++ b/include/dt-bindings/msm/msm-bus-ids.h
@@ -244,7 +244,8 @@
 #define	MSM_BUS_MASTER_PIMEM 141
 #define	MSM_BUS_MASTER_MEM_NOC_SNOC 142
 #define	MSM_BUS_MASTER_IPA_CORE 143
-#define	MSM_BUS_MASTER_MASTER_LAST 144
+#define	MSM_BUS_MASTER_ALC 144
+#define	MSM_BUS_MASTER_MASTER_LAST 145
 
 #define MSM_BUS_MASTER_LLCC_DISPLAY 20000
 #define MSM_BUS_MASTER_MNOC_HF_MEM_NOC_DISPLAY 20001
diff --git a/include/linux/msm-bus.h b/include/linux/msm-bus.h
index 16e3bb2..26e948f 100644
--- a/include/linux/msm-bus.h
+++ b/include/linux/msm-bus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -55,8 +55,14 @@
 	struct msm_bus_vectors *vectors;
 };
 
+struct msm_bus_lat_vectors {
+	uint64_t fal_ns; /* First Access Latency */
+	uint64_t idle_t_ns; /* Idle Time */
+};
+
 struct msm_bus_scale_pdata {
 	struct msm_bus_paths *usecase;
+	struct msm_bus_lat_vectors *usecase_lat;
 	int num_usecases;
 	const char *name;
 	/*
@@ -66,6 +72,11 @@
 	 * of the CPU state.
 	 */
 	unsigned int active_only;
+	/*
+	 * If the ALC(Active Latency Client) flag is set to 1,
+	 * use lat_usecases for latency voting.
+	 */
+	unsigned int alc;
 };
 
 struct msm_bus_client_handle {
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 0de4da6..6b790c6 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -429,7 +429,7 @@
 	geni_write_reg(M_GENI_CMD_ABORT, base, SE_GENI_M_CMD_CTRL_REG);
 }
 
-static inline void qcom_geni_abort_s_cmd(void __iomem *base)
+static inline void geni_abort_s_cmd(void __iomem *base)
 {
 	geni_write_reg(S_GENI_CMD_ABORT, base, SE_GENI_S_CMD_CTRL_REG);
 }
diff --git a/include/linux/seemp_instrumentation.h b/include/linux/seemp_instrumentation.h
new file mode 100644
index 0000000..2c050cb
--- /dev/null
+++ b/include/linux/seemp_instrumentation.h
@@ -0,0 +1,156 @@
+/*
+ * 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __SEEMP_LOGK_STUB__
+#define __SEEMP_LOGK_STUB__
+
+#ifdef CONFIG_SEEMP_CORE
+#include <linux/kernel.h>
+
+#define MAX_BUF_SIZE 188
+
+#define SEEMP_LOGK_API_SIZE sizeof(int)
+
+/* Write: api_id + skip encoding byte + params */
+#define SEEMP_LOGK_RECORD(api_id, format, ...) do {            \
+	*((int *)(buf - SEEMP_LOGK_API_SIZE)) = api_id;             \
+	snprintf(buf + 1, MAX_BUF_SIZE - 1, format, ##__VA_ARGS__); \
+} while (0)
+
+extern void *(*seemp_logk_kernel_begin)(char **buf);
+extern void (*seemp_logk_kernel_end)(void *blck);
+
+static inline void *seemp_setup_buf(char **buf)
+{
+	void *blck;
+
+	if (seemp_logk_kernel_begin && seemp_logk_kernel_end) {
+		blck = seemp_logk_kernel_begin(buf);
+		if (!*buf) {
+			seemp_logk_kernel_end(blck);
+			return NULL;
+		}
+	} else {
+		return NULL;
+	}
+	return blck;
+}
+/*
+ * NOTE: only sendto is going to be instrumented
+ * since send sys call internally calls sendto
+ * with 2 extra parameters
+ */
+static inline void seemp_logk_sendto(int fd, void __user *buff, size_t len,
+		unsigned int flags, struct sockaddr __user *addr, int addr_len)
+{
+	char *buf = NULL;
+	void *blck = NULL;
+
+	/*sets up buf and blck correctly*/
+	blck = seemp_setup_buf(&buf);
+	if (!blck)
+		return;
+
+	/*fill the buf*/
+	SEEMP_LOGK_RECORD(SEEMP_API_kernel__sendto, "len=%u,fd=%d",
+			(unsigned int)len, fd);
+
+	seemp_logk_kernel_end(blck);
+}
+
+/*
+ * NOTE: only recvfrom is going to be instrumented
+ * since recv sys call internally calls recvfrom
+ * with 2 extra parameters
+ */
+static inline void seemp_logk_recvfrom(int fd, void __user *ubuf,
+		size_t size, unsigned int flags, struct sockaddr __user *addr,
+		int __user *addr_len)
+{
+	char *buf = NULL;
+	void *blck = NULL;
+
+	/*sets up buf and blck correctly*/
+	blck = seemp_setup_buf(&buf);
+	if (!blck)
+		return;
+
+	/*fill the buf*/
+	SEEMP_LOGK_RECORD(SEEMP_API_kernel__recvfrom, "size=%u,fd=%d",
+			(unsigned int)size, fd);
+
+	seemp_logk_kernel_end(blck);
+}
+
+static inline void seemp_logk_oom_adjust_write(pid_t pid,
+					kuid_t uid, int oom_adj)
+{
+	char *buf = NULL;
+	void *blck = NULL;
+
+	/*sets up buf and blck correctly*/
+	blck = seemp_setup_buf(&buf);
+	if (!blck)
+		return;
+
+	/*fill the buf*/
+	SEEMP_LOGK_RECORD(SEEMP_API_kernel__oom_adjust_write,
+			 "app_uid=%d,app_pid=%d,oom_adj=%d",
+			uid.val, pid, oom_adj);
+
+	seemp_logk_kernel_end(blck);
+}
+
+static inline void seemp_logk_oom_score_adj_write(pid_t pid, kuid_t uid,
+					int oom_adj_score)
+{
+	char *buf = NULL;
+	void *blck = NULL;
+
+	/*sets up buf and blck correctly*/
+	blck = seemp_setup_buf(&buf);
+	if (!blck)
+		return;
+
+	/*fill the buf*/
+	snprintf(buf, MAX_BUF_SIZE,
+		"-1|kernel|oom_score_adj_write|app_uid=%d,app_pid=%d,oom_adj=%d|--end",
+		uid.val, pid, oom_adj_score);
+
+	seemp_logk_kernel_end(blck);
+}
+
+#else
+static inline void seemp_logk_sendto(int fd, void __user *buff,
+		size_t len, unsigned int flags, struct sockaddr __user *addr,
+		int addr_len)
+{
+}
+
+static inline void seemp_logk_recvfrom
+		(int fd, void __user *ubuf, size_t size,
+		unsigned int flags, struct sockaddr __user *addr,
+		int __user *addr_len)
+{
+}
+
+static inline void seemp_logk_oom_adjust_write
+		(pid_t pid, kuid_t uid, int oom_adj)
+{
+}
+
+static inline void seemp_logk_oom_score_adj_write
+		(pid_t pid, kuid_t uid, int oom_adj_score)
+{
+}
+#endif
+#endif
diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h
index 9ea0736..5478417 100644
--- a/include/soc/qcom/subsystem_restart.h
+++ b/include/soc/qcom/subsystem_restart.h
@@ -1,4 +1,4 @@
-/* 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
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 
 struct subsys_device;
+extern struct bus_type subsys_bus_type;
 
 enum {
 	RESET_SOC = 0,
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 33ba430..7c1899e 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -414,6 +414,8 @@
 header-y += sdla.h
 header-y += seccomp.h
 header-y += securebits.h
+header-y += seemp_api.h
+header-y += seemp_param_id.h
 header-y += selinux_netlink.h
 header-y += sem.h
 header-y += serial_core.h
diff --git a/include/uapi/linux/seemp_api.h b/include/uapi/linux/seemp_api.h
new file mode 100644
index 0000000..4dfc257
--- /dev/null
+++ b/include/uapi/linux/seemp_api.h
@@ -0,0 +1,395 @@
+#ifndef _SEEMP_API_H_
+#define _SEEMP_API_H_
+
+#define SEEMP_API_kernel__oom_adjust_write                                     0
+#define SEEMP_API_kernel__sendto                                               1
+#define SEEMP_API_kernel__recvfrom                                             2
+#define SEEMP_API_View__onTouchEvent                                           3
+#define SEEMP_API_View__onKeyDown                                              4
+#define SEEMP_API_View__onKeyUp                                                5
+#define SEEMP_API_View__onTrackBallEvent                                       6
+#define SEEMP_API_android_provider_Settings__get_ANDROID_ID_                   7
+#define SEEMP_API_TelephonyManager__getDeviceId                                8
+#define SEEMP_API_TelephonyManager__getLine1Number                             9
+#define SEEMP_API_Telephony__query                                            10
+#define SEEMP_API_CallerInfo__getCallerId                                     11
+#define SEEMP_API_CallerInfo__getCallerInfo                                   12
+#define SEEMP_API_ContentResolver__query                                      13
+#define SEEMP_API_AccountManagerService__getPassword                          14
+#define SEEMP_API_AccountManagerService__getUserData                          15
+#define SEEMP_API_AccountManagerService__addAccount                           16
+#define SEEMP_API_AccountManagerService__removeAccount                        17
+#define SEEMP_API_AccountManagerService__setPassword                          18
+#define SEEMP_API_AccountManagerService__clearPassword                        19
+#define SEEMP_API_AccountManagerService__setUserData                          20
+#define SEEMP_API_AccountManagerService__editProperties                       21
+#define SEEMP_API_AccountManager__getPassword                                 22
+#define SEEMP_API_AccountManager__getUserData                                 23
+#define SEEMP_API_AccountManager__addAccountExplicitly                        24
+#define SEEMP_API_AccountManager__removeAccount                               25
+#define SEEMP_API_AccountManager__setPassword                                 26
+#define SEEMP_API_AccountManager__clearPassword                               27
+#define SEEMP_API_AccountManager__setUserData                                 28
+#define SEEMP_API_AccountManager__addAccount                                  29
+#define SEEMP_API_AccountManager__editProperties                              30
+#define SEEMP_API_AccountManager__doWork                                      31
+#define SEEMP_API_Browser__getAllBookmarks                                    32
+#define SEEMP_API_Browser__getAllVisitedUrls                                  33
+#define SEEMP_API_Browser__getVisitedLike                                     34
+#define SEEMP_API_Browser__getVisitedHistory                                  35
+#define SEEMP_API_Browser__requestAllIcons                                    36
+#define SEEMP_API_ContentResolver__insert                                     37
+#define SEEMP_API_CalendarContract__insert                                    38
+#define SEEMP_API_CalendarContract__alarmExists                               39
+#define SEEMP_API_CalendarContract__findNextAlarmTime                         40
+#define SEEMP_API_CalendarContract__query                                     41
+#define SEEMP_API_LocationManager___requestLocationUpdates                    42
+#define SEEMP_API_LocationManager__addGpsStatusListener                       43
+#define SEEMP_API_LocationManager__addNmeaListener                            44
+#define SEEMP_API_LocationManager__addProximityAlert                          45
+#define SEEMP_API_LocationManager__getLastKnownLocation                       46
+#define SEEMP_API_LocationManager__requestLocationUpdates                     47
+#define SEEMP_API_LocationManager__sendExtraCommand                           48
+#define SEEMP_API_TelephonyManager__getCellLocation                           49
+#define SEEMP_API_TelephonyManager__getNeighboringCellInfo                    50
+#define SEEMP_API_GeolocationService__registerForLocationUpdates              51
+#define SEEMP_API_GeolocationService__setEnableGps                            52
+#define SEEMP_API_GeolocationService__start                                   53
+#define SEEMP_API_WebChromeClient__onGeolocationPermissionsShowPrompt         54
+#define SEEMP_API_WifiManager__getScanResults                                 55
+#define SEEMP_API_adB__enable                                                56
+#define SEEMP_API_adB__disable                                                57
+#define SEEMP_API_adB__startDiscovery                                         58
+#define SEEMP_API_adB__listenUsingInsecureRfcommWithServiceRecord             59
+#define SEEMP_API_adB__listenUsingSecureRfcommWithServiceRecord               60
+#define SEEMP_API_adB__getBondedDevices                                       61
+#define SEEMP_API_adB__getRemoteDevice                                        62
+#define SEEMP_API_adB__getState                                               63
+#define SEEMP_API_adB__getProfileConnectionState                              64
+#define SEEMP_API_Camera__takePicture                                         65
+#define SEEMP_API_Camera__setPreviewCallback                                  66
+#define SEEMP_API_Camera__setPreviewCallbackWithBuffer                        67
+#define SEEMP_API_Camera__setOneShotPreviewCallback                           68
+#define SEEMP_API_android_media_MediaRecorder__start                          69
+#define SEEMP_API_AudioRecord__startRecording                                 70
+#define SEEMP_API_AudioRecord__start                                          71
+#define SEEMP_API_SpeechRecognizer__startListening                            72
+#define SEEMP_API_at_SmsManager__sendDataMessage                              73
+#define SEEMP_API_at_SmsManager__sendMultipartTextMessage                     74
+#define SEEMP_API_at_SmsManager__sendTextMessage                              75
+#define SEEMP_API_at_gsm_SmsManager__sendDataMessage                          76
+#define SEEMP_API_at_gsm_SmsManager__sendMultipartTextMessage                 77
+#define SEEMP_API_at_gsm_SmsManager__sendTextMessage                          78
+#define SEEMP_API_at_SmsManager__copyMessageToIcc                             79
+#define SEEMP_API_at_SmsManager__deleteMessageFromIcc                         80
+#define SEEMP_API_at_SmsManager__updateMessageOnIcc                           81
+#define SEEMP_API_at_gsm_SmsManager__copyMessageToSim                         82
+#define SEEMP_API_at_gsm_SmsManager__deleteMessageFromSim                     83
+#define SEEMP_API_at_gsm_SmsManager__updateMessageOnSim                       84
+#define SEEMP_API_at_gsm_SmsManager__getAllMessagesFromSim                    85
+#define SEEMP_API_ContactsContract__getLookupUri                              86
+#define SEEMP_API_ContactsContract__lookupContact                             87
+#define SEEMP_API_ContactsContract__openContactPhotoInputStream               88
+#define SEEMP_API_ContactsContract__getContactLookupUri                       89
+#define SEEMP_API_PackageManagerService__installPackage                       90
+#define SEEMP_API_URL__openConnection                                         91
+#define SEEMP_API_URI__URI                                                    92
+#define SEEMP_API_HttpGet__HttpGet                                            93
+#define SEEMP_API_HttpPut__HttpPut                                            94
+#define SEEMP_API_HttpPost__HttpPost                                          95
+#define SEEMP_API_apS__get_ACCELEROMETER_ROTATION_                           96
+#define SEEMP_API_apS__get_USER_ROTATION_                                    97
+#define SEEMP_API_apS__get_ADB_ENABLED_                                      98
+#define SEEMP_API_apS__get_DEBUG_APP_                                        99
+#define SEEMP_API_apS__get_WAIT_FOR_DEBUGGER_                               100
+#define SEEMP_API_apS__get_AIRPLANE_MODE_ON_                                101
+#define SEEMP_API_apS__get_AIRPLANE_MODE_RADIOS_                            102
+#define SEEMP_API_apS__get_ALARM_ALERT_                                     103
+#define SEEMP_API_apS__get_NEXT_ALARM_FORMATTED_                            104
+#define SEEMP_API_apS__get_ALWAYS_FINISH_ACTIVITIES_                        105
+#define SEEMP_API_apS__get_LOGGING_ID_                                      106
+#define SEEMP_API_apS__get_ANIMATOR_DURATION_SCALE_                         107
+#define SEEMP_API_apS__get_WINDOW_ANIMATION_SCALE_                          108
+#define SEEMP_API_apS__get_FONT_SCALE_                                      109
+#define SEEMP_API_apS__get_SCREEN_BRIGHTNESS_                               110
+#define SEEMP_API_apS__get_SCREEN_BRIGHTNESS_MODE_                          111
+#define SEEMP_API_apS__get_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_                112
+#define SEEMP_API_apS__get_SCREEN_BRIGHTNESS_MODE_MANUAL_                   113
+#define SEEMP_API_apS__get_SCREEN_OFF_TIMEOUT_                              114
+#define SEEMP_API_apS__get_DIM_SCREEN_                                      115
+#define SEEMP_API_apS__get_TRANSITION_ANIMATION_SCALE_                      116
+#define SEEMP_API_apS__get_STAY_ON_WHILE_PLUGGED_IN_                        117
+#define SEEMP_API_apS__get_WALLPAPER_ACTIVITY_                              118
+#define SEEMP_API_apS__get_SHOW_PROCESSES_                                  119
+#define SEEMP_API_apS__get_SHOW_WEB_SUGGESTIONS_                            120
+#define SEEMP_API_apS__get_SHOW_GTALK_SERVICE_STATUS_                       121
+#define SEEMP_API_apS__get_USE_GOOGLE_MAIL_                                 122
+#define SEEMP_API_apS__get_AUTO_TIME_                                       123
+#define SEEMP_API_apS__get_AUTO_TIME_ZONE_                                  124
+#define SEEMP_API_apS__get_DATE_FORMAT_                                     125
+#define SEEMP_API_apS__get_TIME_12_24_                                      126
+#define SEEMP_API_apS__get_BLUETOOTH_DISCOVERABILITY_                       127
+#define SEEMP_API_apS__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_               128
+#define SEEMP_API_apS__get_BLUETOOTH_ON_                                    129
+#define SEEMP_API_apS__get_DEVICE_PROVISIONED_                              130
+#define SEEMP_API_apS__get_SETUP_WIZARD_HAS_RUN_                            131
+#define SEEMP_API_apS__get_DTMF_TONE_WHEN_DIALING_                          132
+#define SEEMP_API_apS__get_END_BUTTON_BEHAVIOR_                             133
+#define SEEMP_API_apS__get_RINGTONE_                                        134
+#define SEEMP_API_apS__get_MODE_RINGER_                                     135
+#define SEEMP_API_apS__get_INSTALL_NON_MARKET_APPS_                         136
+#define SEEMP_API_apS__get_LOCATION_PROVIDERS_ALLOWED_                      137
+#define SEEMP_API_apS__get_LOCK_PATTERN_ENABLED_                            138
+#define SEEMP_API_apS__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_           139
+#define SEEMP_API_apS__get_LOCK_PATTERN_VISIBLE_                            140
+#define SEEMP_API_apS__get_NETWORK_PREFERENCE_                              141
+#define SEEMP_API_apS__get_DATA_ROAMING_                                    142
+#define SEEMP_API_apS__get_HTTP_PROXY_                                      143
+#define SEEMP_API_apS__get_PARENTAL_CONTROL_ENABLED_                        144
+#define SEEMP_API_apS__get_PARENTAL_CONTROL_LAST_UPDATE_                    145
+#define SEEMP_API_apS__get_PARENTAL_CONTROL_REDIRECT_URL_                   146
+#define SEEMP_API_apS__get_RADIO_BLUETOOTH_                                 147
+#define SEEMP_API_apS__get_RADIO_CELL_                                      148
+#define SEEMP_API_apS__get_RADIO_NFC_                                       149
+#define SEEMP_API_apS__get_RADIO_WIFI_                                      150
+#define SEEMP_API_apS__get_SYS_PROP_SETTING_VERSION_                        151
+#define SEEMP_API_apS__get_SETTINGS_CLASSNAME_                              152
+#define SEEMP_API_apS__get_TEXT_AUTO_CAPS_                                  153
+#define SEEMP_API_apS__get_TEXT_AUTO_PUNCTUATE_                             154
+#define SEEMP_API_apS__get_TEXT_AUTO_REPLACE_                               155
+#define SEEMP_API_apS__get_TEXT_SHOW_PASSWORD_                              156
+#define SEEMP_API_apS__get_USB_MASS_STORAGE_ENABLED_                        157
+#define SEEMP_API_apS__get_VIBRATE_ON_                                      158
+#define SEEMP_API_apS__get_HAPTIC_FEEDBACK_ENABLED_                         159
+#define SEEMP_API_apS__get_VOLUME_ALARM_                                    160
+#define SEEMP_API_apS__get_VOLUME_BLUETOOTH_SCO_                            161
+#define SEEMP_API_apS__get_VOLUME_MUSIC_                                    162
+#define SEEMP_API_apS__get_VOLUME_NOTIFICATION_                             163
+#define SEEMP_API_apS__get_VOLUME_RING_                                     164
+#define SEEMP_API_apS__get_VOLUME_SYSTEM_                                   165
+#define SEEMP_API_apS__get_VOLUME_VOICE_                                    166
+#define SEEMP_API_apS__get_SOUND_EFFECTS_ENABLED_                           167
+#define SEEMP_API_apS__get_MODE_RINGER_STREAMS_AFFECTED_                    168
+#define SEEMP_API_apS__get_MUTE_STREAMS_AFFECTED_                           169
+#define SEEMP_API_apS__get_NOTIFICATION_SOUND_                              170
+#define SEEMP_API_apS__get_APPEND_FOR_LAST_AUDIBLE_                         171
+#define SEEMP_API_apS__get_WIFI_MAX_DHCP_RETRY_COUNT_                       172
+#define SEEMP_API_apS__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ 173
+#define SEEMP_API_apS__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_         174
+#define SEEMP_API_apS__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_            175
+#define SEEMP_API_apS__get_WIFI_NUM_OPEN_NETWORKS_KEPT_                     176
+#define SEEMP_API_apS__get_WIFI_ON_                                         177
+#define SEEMP_API_apS__get_WIFI_SLEEP_POLICY_                               178
+#define SEEMP_API_apS__get_WIFI_SLEEP_POLICY_DEFAULT_                       179
+#define SEEMP_API_apS__get_WIFI_SLEEP_POLICY_NEVER_                         180
+#define SEEMP_API_apS__get_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_           181
+#define SEEMP_API_apS__get_WIFI_STATIC_DNS1_                                182
+#define SEEMP_API_apS__get_WIFI_STATIC_DNS2_                                183
+#define SEEMP_API_apS__get_WIFI_STATIC_GATEWAY_                             184
+#define SEEMP_API_apS__get_WIFI_STATIC_IP_                                  185
+#define SEEMP_API_apS__get_WIFI_STATIC_NETMASK_                             186
+#define SEEMP_API_apS__get_WIFI_USE_STATIC_IP_                              187
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ 188
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_AP_COUNT_                          189
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_         190
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_          191
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_       192
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_        193
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_MAX_AP_CHECKS_                     194
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_ON_                                195
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_PING_COUNT_                        196
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_PING_DELAY_MS_                     197
+#define SEEMP_API_apS__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_                   198
+#define SEEMP_API_apS__put_ACCELEROMETER_ROTATION_                          199
+#define SEEMP_API_apS__put_USER_ROTATION_                                   200
+#define SEEMP_API_apS__put_ADB_ENABLED_                                     201
+#define SEEMP_API_apS__put_DEBUG_APP_                                       202
+#define SEEMP_API_apS__put_WAIT_FOR_DEBUGGER_                               203
+#define SEEMP_API_apS__put_AIRPLANE_MODE_ON_                                204
+#define SEEMP_API_apS__put_AIRPLANE_MODE_RADIOS_                            205
+#define SEEMP_API_apS__put_ALARM_ALERT_                                     206
+#define SEEMP_API_apS__put_NEXT_ALARM_FORMATTED_                            207
+#define SEEMP_API_apS__put_ALWAYS_FINISH_ACTIVITIES_                        208
+#define SEEMP_API_apS__put_ANDROID_ID_                                      209
+#define SEEMP_API_apS__put_LOGGING_ID_                                      210
+#define SEEMP_API_apS__put_ANIMATOR_DURATION_SCALE_                         211
+#define SEEMP_API_apS__put_WINDOW_ANIMATION_SCALE_                          212
+#define SEEMP_API_apS__put_FONT_SCALE_                                      213
+#define SEEMP_API_apS__put_SCREEN_BRIGHTNESS_                               214
+#define SEEMP_API_apS__put_SCREEN_BRIGHTNESS_MODE_                          215
+#define SEEMP_API_apS__put_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_                216
+#define SEEMP_API_apS__put_SCREEN_BRIGHTNESS_MODE_MANUAL_                   217
+#define SEEMP_API_apS__put_SCREEN_OFF_TIMEOUT_                              218
+#define SEEMP_API_apS__put_DIM_SCREEN_                                      219
+#define SEEMP_API_apS__put_TRANSITION_ANIMATION_SCALE_                      220
+#define SEEMP_API_apS__put_STAY_ON_WHILE_PLUGGED_IN_                        221
+#define SEEMP_API_apS__put_WALLPAPER_ACTIVITY_                              222
+#define SEEMP_API_apS__put_SHOW_PROCESSES_                                  223
+#define SEEMP_API_apS__put_SHOW_WEB_SUGGESTIONS_                            224
+#define SEEMP_API_apS__put_SHOW_GTALK_SERVICE_STATUS_                       225
+#define SEEMP_API_apS__put_USE_GOOGLE_MAIL_                                 226
+#define SEEMP_API_apS__put_AUTO_TIME_                                       227
+#define SEEMP_API_apS__put_AUTO_TIME_ZONE_                                  228
+#define SEEMP_API_apS__put_DATE_FORMAT_                                     229
+#define SEEMP_API_apS__put_TIME_12_24_                                      230
+#define SEEMP_API_apS__put_BLUETOOTH_DISCOVERABILITY_                       231
+#define SEEMP_API_apS__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_               232
+#define SEEMP_API_apS__put_BLUETOOTH_ON_                                    233
+#define SEEMP_API_apS__put_DEVICE_PROVISIONED_                              234
+#define SEEMP_API_apS__put_SETUP_WIZARD_HAS_RUN_                            235
+#define SEEMP_API_apS__put_DTMF_TONE_WHEN_DIALING_                          236
+#define SEEMP_API_apS__put_END_BUTTON_BEHAVIOR_                             237
+#define SEEMP_API_apS__put_RINGTONE_                                        238
+#define SEEMP_API_apS__put_MODE_RINGER_                                     239
+#define SEEMP_API_apS__put_INSTALL_NON_MARKET_APPS_                         240
+#define SEEMP_API_apS__put_LOCATION_PROVIDERS_ALLOWED_                      241
+#define SEEMP_API_apS__put_LOCK_PATTERN_ENABLED_                            242
+#define SEEMP_API_apS__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_           243
+#define SEEMP_API_apS__put_LOCK_PATTERN_VISIBLE_                            244
+#define SEEMP_API_apS__put_NETWORK_PREFERENCE_                              245
+#define SEEMP_API_apS__put_DATA_ROAMING_                                    246
+#define SEEMP_API_apS__put_HTTP_PROXY_                                      247
+#define SEEMP_API_apS__put_PARENTAL_CONTROL_ENABLED_                        248
+#define SEEMP_API_apS__put_PARENTAL_CONTROL_LAST_UPDATE_                    249
+#define SEEMP_API_apS__put_PARENTAL_CONTROL_REDIRECT_URL_                   250
+#define SEEMP_API_apS__put_RADIO_BLUETOOTH_                                 251
+#define SEEMP_API_apS__put_RADIO_CELL_                                      252
+#define SEEMP_API_apS__put_RADIO_NFC_                                       253
+#define SEEMP_API_apS__put_RADIO_WIFI_                                      254
+#define SEEMP_API_apS__put_SYS_PROP_SETTING_VERSION_                        255
+#define SEEMP_API_apS__put_SETTINGS_CLASSNAME_                              256
+#define SEEMP_API_apS__put_TEXT_AUTO_CAPS_                                  257
+#define SEEMP_API_apS__put_TEXT_AUTO_PUNCTUATE_                             258
+#define SEEMP_API_apS__put_TEXT_AUTO_REPLACE_                               259
+#define SEEMP_API_apS__put_TEXT_SHOW_PASSWORD_                              260
+#define SEEMP_API_apS__put_USB_MASS_STORAGE_ENABLED_                        261
+#define SEEMP_API_apS__put_VIBRATE_ON_                                      262
+#define SEEMP_API_apS__put_HAPTIC_FEEDBACK_ENABLED_                         263
+#define SEEMP_API_apS__put_VOLUME_ALARM_                                    264
+#define SEEMP_API_apS__put_VOLUME_BLUETOOTH_SCO_                            265
+#define SEEMP_API_apS__put_VOLUME_MUSIC_                                    266
+#define SEEMP_API_apS__put_VOLUME_NOTIFICATION_                             267
+#define SEEMP_API_apS__put_VOLUME_RING_                                     268
+#define SEEMP_API_apS__put_VOLUME_SYSTEM_                                   269
+#define SEEMP_API_apS__put_VOLUME_VOICE_                                    270
+#define SEEMP_API_apS__put_SOUND_EFFECTS_ENABLED_                           271
+#define SEEMP_API_apS__put_MODE_RINGER_STREAMS_AFFECTED_                    272
+#define SEEMP_API_apS__put_MUTE_STREAMS_AFFECTED_                           273
+#define SEEMP_API_apS__put_NOTIFICATION_SOUND_                              274
+#define SEEMP_API_apS__put_APPEND_FOR_LAST_AUDIBLE_                         275
+#define SEEMP_API_apS__put_WIFI_MAX_DHCP_RETRY_COUNT_                       276
+#define SEEMP_API_apS__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ 277
+#define SEEMP_API_apS__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_         278
+#define SEEMP_API_apS__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_            279
+#define SEEMP_API_apS__put_WIFI_NUM_OPEN_NETWORKS_KEPT_                     280
+#define SEEMP_API_apS__put_WIFI_ON_                                         281
+#define SEEMP_API_apS__put_WIFI_SLEEP_POLICY_                               282
+#define SEEMP_API_apS__put_WIFI_SLEEP_POLICY_DEFAULT_                       283
+#define SEEMP_API_apS__put_WIFI_SLEEP_POLICY_NEVER_                         284
+#define SEEMP_API_apS__put_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_           285
+#define SEEMP_API_apS__put_WIFI_STATIC_DNS1_                                286
+#define SEEMP_API_apS__put_WIFI_STATIC_DNS2_                                287
+#define SEEMP_API_apS__put_WIFI_STATIC_GATEWAY_                             288
+#define SEEMP_API_apS__put_WIFI_STATIC_IP_                                  289
+#define SEEMP_API_apS__put_WIFI_STATIC_NETMASK_                             290
+#define SEEMP_API_apS__put_WIFI_USE_STATIC_IP_                              291
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ 292
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_AP_COUNT_                          293
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_         294
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_          295
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_       296
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_        297
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_MAX_AP_CHECKS_                     298
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_ON_                                299
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_PING_COUNT_                        300
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_PING_DELAY_MS_                     301
+#define SEEMP_API_apS__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_                   302
+#define SEEMP_API_Poll__setCumulativeWifiRxMBytes                           303
+#define SEEMP_API_Poll__setInstantaneousWifiRxMBytes                        304
+#define SEEMP_API_Poll__setCumulativeWifiRxPackets                          305
+#define SEEMP_API_Poll__setInstantaneousWifiRxPackets                       306
+#define SEEMP_API_Poll__setCumulativeWifiTxMBytes                           307
+#define SEEMP_API_Poll__setInstantaneousWifiTxMBytes                        308
+#define SEEMP_API_Poll__setCumulativeWifiTxPackets                          309
+#define SEEMP_API_Poll__setInstantaneousWifiTxPackets                       310
+#define SEEMP_API_Poll__setCumulativeWifiRxTcpMBytes                        311
+#define SEEMP_API_Poll__setInstantaneousWifiRxTcpMBytes                     312
+#define SEEMP_API_Poll__setCumulativeWifiRxTcpPackets                       313
+#define SEEMP_API_Poll__setInstantaneousWifiRxTcpPackets                    314
+#define SEEMP_API_Poll__setCumulativeWifiRxUdpMBytes                        315
+#define SEEMP_API_Poll__setInstantaneousWifiRxUdpMBytes                     316
+#define SEEMP_API_Poll__setCumulativeWifiRxUdpPackets                       317
+#define SEEMP_API_Poll__setInstantaneousWifiRxUdpPackets                    318
+#define SEEMP_API_Poll__setCumulativeWifiRxOtherMBytes                      319
+#define SEEMP_API_Poll__setInstantaneousWifiRxOtherMBytes                   320
+#define SEEMP_API_Poll__setCumulativeWifiRxOtherPackets                     321
+#define SEEMP_API_Poll__setInstantaneousWifiRxOtherPackets                  322
+#define SEEMP_API_Poll__setCumulativeWifiTxTcpMBytes                        323
+#define SEEMP_API_Poll__setInstantaneousWifiTxTcpMBytes                     324
+#define SEEMP_API_Poll__setCumulativeWifiTxTcpPackets                       325
+#define SEEMP_API_Poll__setInstantaneousWifiTxTcpPackets                    326
+#define SEEMP_API_Poll__setCumulativeWifiTxUdpMBytes                        327
+#define SEEMP_API_Poll__setInstantaneousWifiTxUdpMBytes                     328
+#define SEEMP_API_Poll__setCumulativeWifiTxUdpPackets                       329
+#define SEEMP_API_Poll__setInstantaneousWifiTxUdpPackets                    330
+#define SEEMP_API_Poll__setCumulativeWifiTxOtherMBytes                      331
+#define SEEMP_API_Poll__setInstantaneousWifiTxOtherMBytes                   332
+#define SEEMP_API_Poll__setCumulativeWifiTxOtherPackets                     333
+#define SEEMP_API_Poll__setInstantaneousWifiTxOtherPackets                  334
+#define SEEMP_API_Poll__setCumulativeMobileRxMBytes                         335
+#define SEEMP_API_Poll__setInstantaneousMobileRxMBytes                      336
+#define SEEMP_API_Poll__setCumulativeMobileRxPackets                        337
+#define SEEMP_API_Poll__setInstantaneousMobileRxPackets                     338
+#define SEEMP_API_Poll__setCumulativeMobileTxMBytes                         339
+#define SEEMP_API_Poll__setInstantaneousMobileTxMBytes                      340
+#define SEEMP_API_Poll__setCumulativeMobileTxPackets                        341
+#define SEEMP_API_Poll__setInstantaneousMobileTxPackets                     342
+#define SEEMP_API_Poll__setCumulativeMobileRxTcpMBytes                      343
+#define SEEMP_API_Poll__setInstantaneousMobileRxTcpMBytes                   344
+#define SEEMP_API_Poll__setCumulativeMobileRxTcpPackets                     345
+#define SEEMP_API_Poll__setInstantaneousMobileRxTcpPackets                  346
+#define SEEMP_API_Poll__setCumulativeMobileRxUdpMBytes                      347
+#define SEEMP_API_Poll__setInstantaneousMobileRxUdpMBytes                   348
+#define SEEMP_API_Poll__setCumulativeMobileRxUdpPackets                     349
+#define SEEMP_API_Poll__setInstantaneousMobileRxUdpPackets                  350
+#define SEEMP_API_Poll__setCumulativeMobileRxOtherMBytes                    351
+#define SEEMP_API_Poll__setInstantaneousMobileRxOtherMBytes                 352
+#define SEEMP_API_Poll__setCumulativeMobileRxOtherPackets                   353
+#define SEEMP_API_Poll__setInstantaneousMobileRxOtherPackets                354
+#define SEEMP_API_Poll__setCumulativeMobileTxTcpMBytes                      355
+#define SEEMP_API_Poll__setInstantaneousMobileTxTcpMBytes                   356
+#define SEEMP_API_Poll__setCumulativeMobileTxTcpPackets                     357
+#define SEEMP_API_Poll__setInstantaneousMobileTxTcpPackets                  358
+#define SEEMP_API_Poll__setCumulativeMobileTxUdpMBytes                      359
+#define SEEMP_API_Poll__setInstantaneousMobileTxUdpMBytes                   360
+#define SEEMP_API_Poll__setCumulativeMobileTxUdpPackets                     361
+#define SEEMP_API_Poll__setInstantaneousMobileTxUdpPackets                  362
+#define SEEMP_API_Poll__setCumulativeMobileTxOtherMBytes                    363
+#define SEEMP_API_Poll__setInstantaneousMobileTxOtherMBytes                 364
+#define SEEMP_API_Poll__setCumulativeMobileTxOtherPackets                   365
+#define SEEMP_API_Poll__setInstantaneousMobileTxOtherPackets                366
+#define SEEMP_API_Poll__setNumSockets                                       367
+#define SEEMP_API_Poll__setNumTcpStateListen                                368
+#define SEEMP_API_Poll__setNumTcpStateEstablished                           369
+#define SEEMP_API_Poll__setNumLocalIp                                       370
+#define SEEMP_API_Poll__setNumLocalPort                                     371
+#define SEEMP_API_Poll__setNumRemoteIp                                      372
+#define SEEMP_API_Poll__setNumRemotePort                                    373
+#define SEEMP_API_Poll__setNumRemoteTuple                                   374
+#define SEEMP_API_Poll__setNumInode                                         375
+#define SEEMP_API_Instrumentation__startActivitySync                        376
+#define SEEMP_API_Instrumentation__execStartActivity                        377
+#define SEEMP_API_Instrumentation__execStartActivitiesAsUser                378
+#define SEEMP_API_Instrumentation__execStartActivityAsCaller                379
+#define SEEMP_API_Instrumentation__execStartActivityFromAppTask             380
+#define SEEMP_API_ah_SystemSensorManager__registerListenerImpl              381
+#define SEEMP_API_ah_SystemSensorManager__unregisterListenerImpl            382
+#define SEEMP_API_WindowManagerImpl__addView                                383
+#define SEEMP_API_WindowManagerImpl__updateViewLayout                       384
+#define SEEMP_API_ActivityManagerService__applyOomAdjLocked                 385
+#define SEEMP_API_ProcessRecord__makeActive                                 386
+#define SEEMP_API_ProcessRecord__makeInactive                               387
+#define SEEMP_API_TelephonyManager__getSimSerialNumber                      388
+#define SEEMP_API_TelephonyManager__getSubscriberId                         389
+
+#endif /* _SEEMP_API_H_*/
diff --git a/include/uapi/linux/seemp_param_id.h b/include/uapi/linux/seemp_param_id.h
new file mode 100644
index 0000000..8f1f05f
--- /dev/null
+++ b/include/uapi/linux/seemp_param_id.h
@@ -0,0 +1,90 @@
+#ifndef _PARAM_ID_H_
+#define _PARAM_ID_H_
+
+#define PARAM_ID_LEN 0
+#define PARAM_ID_OOM_ADJ 1
+#define PARAM_ID_APP_UID 2
+#define PARAM_ID_APP_PID 3
+#define PARAM_ID_VALUE 4
+#define PARAM_ID_SIZE 5
+#define PARAM_ID_FD 6
+#define PARAM_ID_RATE 7
+#define PARAM_ID_SENSOR 8
+#define PARAM_ID_WINDOW_TYPE 9
+#define PARAM_ID_WINDOW_FLAG 10
+#define NUM_PARAM_IDS 11
+
+static inline int param_id_index(const char *param, const char *end)
+{
+	int id  = -1;
+	int len = ((end != NULL) ? (end - param) : (int)strlen(param));
+
+	if ((len == 3) && !memcmp(param, "len", 3))
+		id = 0;
+	else if ((len == 7) && !memcmp(param, "oom_adj", 7))
+		id = 1;
+	else if ((len == 7) && !memcmp(param, "app_uid", 7))
+		id = 2;
+	else if ((len == 7) && !memcmp(param, "app_pid", 7))
+		id = 3;
+	else if ((len == 5) && !memcmp(param, "value", 5))
+		id = 4;
+	else if ((len == 4) && !memcmp(param, "size", 4))
+		id = 5;
+	else if ((len == 2) && !memcmp(param, "fd", 2))
+		id = 6;
+	else if ((len == 4) && !memcmp(param, "rate", 4))
+		id = 7;
+	else if ((len == 6) && !memcmp(param, "sensor", 6))
+		id = 8;
+	else if ((len == 11) && !memcmp(param, "window_type", 11))
+		id = 9;
+	else if ((len == 11) && !memcmp(param, "window_flag", 11))
+		id = 10;
+
+	return id;
+}
+
+static inline const char *get_param_id_name(int id)
+{
+	const char *name = "?";
+
+	switch (id) {
+	case 0:
+		name = "len";
+		break;
+	case 1:
+		name = "oom_adj";
+		break;
+	case 2:
+		name = "app_uid";
+		break;
+	case 3:
+		name = "app_pid";
+		break;
+	case 4:
+		name = "value";
+		break;
+	case 5:
+		name = "size";
+		break;
+	case 6:
+		name = "fd";
+		break;
+	case 7:
+		name = "rate";
+		break;
+	case 8:
+		name = "sensor";
+		break;
+	case 9:
+		name = "window_type";
+		break;
+	case 10:
+		name = "window_flag";
+		break;
+	}
+	return name;
+}
+
+#endif /* _PARAM_ID_H_ */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 69df75d..1d203e1 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1122,8 +1122,9 @@
 
 	if (!switch_err) {
 		switch_err = switch_to_fair_policy();
-		pr_err("Hotplug policy switch err. Task %s pid=%d\n",
-					current->comm, current->pid);
+		if (switch_err)
+			pr_err("Hotplug policy switch err=%d Task %s pid=%d\n",
+				switch_err, current->comm, current->pid);
 	}
 
 	return err;
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index a58bdb0..1040a43 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -35,6 +35,7 @@
 	unsigned int busy_down_thres[MAX_CPUS_PER_CLUSTER];
 	unsigned int active_cpus;
 	unsigned int num_cpus;
+	unsigned int nr_isolated_cpus;
 	cpumask_t cpu_mask;
 	unsigned int need_cpus;
 	unsigned int task_thres;
@@ -264,6 +265,7 @@
 	ssize_t count = 0;
 	unsigned int cpu;
 
+	spin_lock_irq(&state_lock);
 	for_each_possible_cpu(cpu) {
 		c = &per_cpu(cpu_state, cpu);
 		cluster = c->cluster;
@@ -297,8 +299,12 @@
 		count += snprintf(buf + count, PAGE_SIZE - count,
 				"\tNeed CPUs: %u\n", cluster->need_cpus);
 		count += snprintf(buf + count, PAGE_SIZE - count,
+				"\tNr isolated CPUs: %u\n",
+						cluster->nr_isolated_cpus);
+		count += snprintf(buf + count, PAGE_SIZE - count,
 				"\tBoost: %u\n", (unsigned int) cluster->boost);
 	}
+	spin_unlock_irq(&state_lock);
 
 	return count;
 }
@@ -531,7 +537,7 @@
 							unsigned int need)
 {
 	return (need < cluster->active_cpus || (need > cluster->active_cpus &&
-	    sched_isolate_count(&cluster->cpu_mask, false)));
+						cluster->nr_isolated_cpus));
 }
 
 static bool eval_need(struct cluster_data *cluster)
@@ -541,9 +547,8 @@
 	unsigned int need_cpus = 0, last_need, thres_idx;
 	int ret = 0;
 	bool need_flag = false;
-	unsigned int active_cpus;
 	unsigned int new_need;
-	s64 now;
+	s64 now, elapsed;
 
 	if (unlikely(!cluster->inited))
 		return 0;
@@ -553,8 +558,8 @@
 	if (cluster->boost) {
 		need_cpus = cluster->max_cpus;
 	} else {
-		active_cpus = get_active_cpu_count(cluster);
-		thres_idx = active_cpus ? active_cpus - 1 : 0;
+		cluster->active_cpus = get_active_cpu_count(cluster);
+		thres_idx = cluster->active_cpus ? cluster->active_cpus - 1 : 0;
 		list_for_each_entry(c, &cluster->lru, sib) {
 			if (c->busy >= cluster->busy_up_thres[thres_idx])
 				c->is_busy = true;
@@ -570,17 +575,16 @@
 	last_need = cluster->need_cpus;
 	now = ktime_to_ms(ktime_get());
 
-	if (new_need == last_need) {
-		cluster->need_ts = now;
-		spin_unlock_irqrestore(&state_lock, flags);
-		return 0;
-	}
-
-	if (need_cpus > cluster->active_cpus) {
+	if (new_need > cluster->active_cpus) {
 		ret = 1;
-	} else if (need_cpus < cluster->active_cpus) {
-		s64 elapsed = now - cluster->need_ts;
+	} else {
+		if (new_need == last_need) {
+			cluster->need_ts = now;
+			spin_unlock_irqrestore(&state_lock, flags);
+			return 0;
+		}
 
+		elapsed =  now - cluster->need_ts;
 		ret = elapsed >= cluster->offline_delay_ms;
 	}
 
@@ -588,7 +592,7 @@
 		cluster->need_ts = now;
 		cluster->need_cpus = new_need;
 	}
-	trace_core_ctl_eval_need(cluster->first_cpu, last_need, need_cpus,
+	trace_core_ctl_eval_need(cluster->first_cpu, last_need, new_need,
 				 ret && need_flag);
 	spin_unlock_irqrestore(&state_lock, flags);
 
@@ -724,6 +728,7 @@
 	struct cpu_data *c, *tmp;
 	unsigned long flags;
 	unsigned int num_cpus = cluster->num_cpus;
+	unsigned int nr_isolated = 0;
 
 	/*
 	 * Protect against entry being removed (and added at tail) by other
@@ -748,12 +753,14 @@
 		if (!sched_isolate_cpu(c->cpu)) {
 			c->isolated_by_us = true;
 			move_cpu_lru(c);
+			nr_isolated++;
 		} else {
 			pr_debug("Unable to isolate CPU%u\n", c->cpu);
 		}
 		cluster->active_cpus = get_active_cpu_count(cluster);
 		spin_lock_irqsave(&state_lock, flags);
 	}
+	cluster->nr_isolated_cpus += nr_isolated;
 	spin_unlock_irqrestore(&state_lock, flags);
 
 	/*
@@ -763,6 +770,7 @@
 	if (cluster->active_cpus <= cluster->max_cpus)
 		return;
 
+	nr_isolated = 0;
 	num_cpus = cluster->num_cpus;
 	spin_lock_irqsave(&state_lock, flags);
 	list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
@@ -780,12 +788,14 @@
 		if (!sched_isolate_cpu(c->cpu)) {
 			c->isolated_by_us = true;
 			move_cpu_lru(c);
+			nr_isolated++;
 		} else {
 			pr_debug("Unable to isolate CPU%u\n", c->cpu);
 		}
 		cluster->active_cpus = get_active_cpu_count(cluster);
 		spin_lock_irqsave(&state_lock, flags);
 	}
+	cluster->nr_isolated_cpus += nr_isolated;
 	spin_unlock_irqrestore(&state_lock, flags);
 
 }
@@ -796,6 +806,7 @@
 	struct cpu_data *c, *tmp;
 	unsigned long flags;
 	unsigned int num_cpus = cluster->num_cpus;
+	unsigned int nr_unisolated = 0;
 
 	/*
 	 * Protect against entry being removed (and added at tail) by other
@@ -820,12 +831,14 @@
 		if (!sched_unisolate_cpu(c->cpu)) {
 			c->isolated_by_us = false;
 			move_cpu_lru(c);
+			nr_unisolated++;
 		} else {
 			pr_debug("Unable to unisolate CPU%u\n", c->cpu);
 		}
 		cluster->active_cpus = get_active_cpu_count(cluster);
 		spin_lock_irqsave(&state_lock, flags);
 	}
+	cluster->nr_isolated_cpus -= nr_unisolated;
 	spin_unlock_irqrestore(&state_lock, flags);
 }
 
@@ -891,10 +904,11 @@
 	struct cpu_data *state = &per_cpu(cpu_state, cpu);
 	struct cluster_data *cluster = state->cluster;
 	unsigned int need;
-	int ret = NOTIFY_OK;
+	bool do_wakeup, unisolated = false;
+	unsigned long flags;
 
 	if (unlikely(!cluster || !cluster->inited))
-		return NOTIFY_OK;
+		return NOTIFY_DONE;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
@@ -917,6 +931,7 @@
 		if (state->isolated_by_us) {
 			sched_unisolate_cpu_unlocked(cpu);
 			state->isolated_by_us = false;
+			unisolated = true;
 		}
 
 		/* Move a CPU to the end of the LRU when it goes offline. */
@@ -925,13 +940,20 @@
 		state->busy = 0;
 		cluster->active_cpus = get_active_cpu_count(cluster);
 		break;
+	default:
+		return NOTIFY_DONE;
 	}
 
 	need = apply_limits(cluster, cluster->need_cpus);
-	if (adjustment_possible(cluster, need))
+	spin_lock_irqsave(&state_lock, flags);
+	if (unisolated)
+		cluster->nr_isolated_cpus--;
+	do_wakeup = adjustment_possible(cluster, need);
+	spin_unlock_irqrestore(&state_lock, flags);
+	if (do_wakeup)
 		wake_up_core_ctl_thread(cluster);
 
-	return ret;
+	return NOTIFY_OK;
 }
 
 static struct notifier_block __refdata cpu_notifier = {
diff --git a/net/socket.c b/net/socket.c
index 40beb5a..a4fb472 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -89,6 +89,8 @@
 #include <linux/magic.h>
 #include <linux/slab.h>
 #include <linux/xattr.h>
+#include <linux/seemp_api.h>
+#include <linux/seemp_instrumentation.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -1646,6 +1648,8 @@
 	struct iovec iov;
 	int fput_needed;
 
+	seemp_logk_sendto(fd, buff, len, flags, addr, addr_len);
+
 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
 	if (unlikely(err))
 		return err;