Merge "Merge android-4.9.152 (fd37e28) into msm-4.9"
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 7233829..ceb7bcb 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -49,12 +49,32 @@
 KERNEL_CROSS_COMPILE := $(TARGET_KERNEL_CROSS_COMPILE_PREFIX)
 endif
 
+ifeq ($(KERNEL_LLVM_SUPPORT), true)
+  ifeq ($(KERNEL_SD_LLVM_SUPPORT), true)  #Using sd-llvm compiler
+    ifeq ($(shell echo $(SDCLANG_PATH) | head -c 1),/)
+       KERNEL_LLVM_BIN := $(SDCLANG_PATH)/clang
+    else
+       KERNEL_LLVM_BIN := $(shell pwd)/$(SDCLANG_PATH)/clang
+    endif
+    $(warning "Using sdllvm" $(KERNEL_LLVM_BIN))
+  else
+     KERNEL_LLVM_BIN := $(shell pwd)/$(CLANG) #Using aosp-llvm compiler
+    $(warning "Using aosp-llvm" $(KERNEL_LLVM_BIN))
+  endif
+endif
+
 ifeq ($(TARGET_PREBUILT_KERNEL),)
 
 KERNEL_GCC_NOANDROID_CHK := $(shell (echo "int main() {return 0;}" | $(KERNEL_CROSS_COMPILE)gcc -E -mno-android - > /dev/null 2>&1 ; echo $$?))
+
+real_cc :=
+ifeq ($(KERNEL_LLVM_SUPPORT),true)
+real_cc := REAL_CC=$(KERNEL_LLVM_BIN) CLANG_TRIPLE=aarch64-linux-gnu-
+else
 ifeq ($(strip $(KERNEL_GCC_NOANDROID_CHK)),0)
 KERNEL_CFLAGS := KCFLAGS=-mno-android
 endif
+endif
 
 mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
 current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
@@ -151,52 +171,52 @@
 	mkdir -p $(KERNEL_VM_OUT);
 
 $(KERNEL_VM_CONFIG): $(KERNEL_VM_OUT)
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_VM_DEFCONFIG);
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_VM_DEFCONFIG);
 	if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
 		echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
 		echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_VM_OUT)/.config; \
-		$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi;
+		$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) oldconfig; fi;
 
 $(TARGET_PREBUILT_INT_KERNEL_VM): $(KERNEL_VM_OUT) $(KERNEL_VM_HEADERS_INSTALL)
 	echo "Building vm kernel...";
 	rm -rf $(KERNEL_VM_OUT)/arch/$(KERNEL_ARCH)/boot/dts;
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_CFLAGS);
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_CFLAGS);
 
 $(KERNEL_VM_HEADERS_INSTALL): $(KERNEL_VM_OUT)
 	rm -f $(BUILD_ROOT_LOC)$(KERNEL_VM_CONFIG);
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_VM_DEFCONFIG);
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) headers_install;
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_VM_DEFCONFIG);
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) headers_install;
 	if [ -d "$(KERNEL_VM_HEADERS_INSTALL)/include/bringup_headers" ]; then \
 		cp -Rf  $(KERNEL_VM_HEADERS_INSTALL)/include/bringup_headers/* $(KERNEL_VM_HEADERS_INSTALL)/include/ ; fi ;
 	if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
 		echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_VM_OUT)/.config; \
-		$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi;
+		$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_VM_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) oldconfig; fi;
 endif
 
 $(KERNEL_OUT):
 	mkdir -p $(KERNEL_OUT)
 
 $(KERNEL_CONFIG): $(KERNEL_OUT)
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG)
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_DEFCONFIG)
 	$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
 			echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
 			echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
-			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi
+			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) oldconfig; fi
 
 $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL)
 	$(hide) echo "Building kernel..."
 	$(hide) rm -rf $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/dts
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_CFLAGS)
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_CFLAGS) modules
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) INSTALL_MOD_PATH=$(BUILD_ROOT_LOC)../$(KERNEL_MODULES_INSTALL) INSTALL_MOD_STRIP=1 $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) modules_install
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_CFLAGS)
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_CFLAGS) modules
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) INSTALL_MOD_PATH=$(BUILD_ROOT_LOC)../$(KERNEL_MODULES_INSTALL) INSTALL_MOD_STRIP=1 $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) modules_install
 	$(mv-modules)
 	$(clean-module-folder)
 
 $(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT)
 	$(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \
 			rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
-			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_HEADER_DEFCONFIG); \
-			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) headers_install;\
+			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_HEADER_DEFCONFIG); \
+			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) headers_install;\
 			if [ -d "$(KERNEL_HEADERS_INSTALL)/include/bringup_headers" ]; then \
 				cp -Rf  $(KERNEL_HEADERS_INSTALL)/include/bringup_headers/* $(KERNEL_HEADERS_INSTALL)/include/ ;\
 			fi ;\
@@ -204,22 +224,22 @@
 	$(hide) if [ "$(KERNEL_HEADER_DEFCONFIG)" != "$(KERNEL_DEFCONFIG)" ]; then \
 			echo "Used a different defconfig for header generation"; \
 			rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
-			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG); fi
+			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_DEFCONFIG); fi
 	$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
 			echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
 			echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
-			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi
+			$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) oldconfig; fi
 
 .PHONY: kerneltags
 kerneltags: $(KERNEL_OUT) $(KERNEL_CONFIG)
-	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) tags
+	$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) tags
 
 .PHONY: kernelconfig
 kernelconfig: $(KERNEL_OUT) $(KERNEL_CONFIG)
 	env KCONFIG_NOTIMESTAMP=true \
-	     $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) menuconfig
+	     $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) menuconfig
 	env KCONFIG_NOTIMESTAMP=true \
-	     $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) savedefconfig
+	     $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) savedefconfig
 	cp $(KERNEL_OUT)/defconfig $(TARGET_KERNEL_SOURCE)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_DEFCONFIG)
 
 endif
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
index 75f901b..fd53d9f 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
@@ -30,6 +30,7 @@
 			"qcom,gcc-8917"
 			"qcom,gcc-8940"
 			"qcom,gcc-8920"
+			"qcom,gcc-qm215"
 			"qcom,gcc-spm-8952"
 			"qcom,gcc-spm-8937"
 			"qcom,rpmcc-8909"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index ab58089..771ca5a 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -283,6 +283,7 @@
 compatible = "qcom,msm8917-qrd"
 compatible = "qcom,msm8917-qrd-sku5"
 compatible = "qcom,msm8940-mtp"
+compatible = "qcom,msm8940-cdp"
 compatible = "qcom,msm8926-cdp"
 compatible = "qcom,msm8926-mtp"
 compatible = "qcom,msm8926-qrd"
diff --git a/Documentation/devicetree/bindings/cnss/cnss-sdio-wlan.txt b/Documentation/devicetree/bindings/cnss/cnss-sdio-wlan.txt
index 0149ad3..fbd136e 100644
--- a/Documentation/devicetree/bindings/cnss/cnss-sdio-wlan.txt
+++ b/Documentation/devicetree/bindings/cnss/cnss-sdio-wlan.txt
@@ -31,6 +31,12 @@
   - qcom,msm-bus,vectors-KBps: bus scale vector table.
   - qcom,skip-wlan-en-toggle: Boolean property to be enabled for platforms where
                            wlan_en toggling is not supported.
+  - vdd-wlan-xtal-min: Minimum required voltage in uV for VDD_XTAL regulator.
+			   Minimum required voltage is 1620000.
+			   If not set, a typical 1800000 will be set.
+  - vdd-wlan-xtal-max: Maximum acceptable voltage in uV for VDD_XTAL regulator.
+			   Maximum acceptable voltage is 3465000.
+			   If not set, a typical 1800000 will be set.
 Example:
 	qcom,cnss-sdio {
 		compatible = "qcom,cnss_sdio";
diff --git a/Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt b/Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt
new file mode 100644
index 0000000..f522784
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt
@@ -0,0 +1,83 @@
+The IAM20680 sensor is 6-axis gyroscope+accelerometer combo
+device which is made by InvenSense Inc.
+
+Required properties:
+
+ - compatible   : Should be "invn,iam20680".
+ - reg          : the I2C address which depends on the AD0 pin.
+ - gpios        : INVENSENSE GPIO in the format described by ../gpio/gpio.txt
+
+Optional properties:
+ - inven,vdd_ana-supply :
+ - inven,vcc_i2c-supply :
+ - inven,gpio_int1 :
+ - axis_map_x :
+ - axis_map_y :
+ - axis_map_z :
+ - negate_x   :
+ - negate_y   :
+ - negate_z   :
+ - fs_range :
+ - poll_interval :
+ - min_interval :
+ - inven,secondary_reg :
+ - inven,secondary_type :
+ - inven,secondary_name :
+ - inven,secondary_axis_map_x :
+ - inven,secondary_axis_map_y :
+ - inven,secondary_axis_map_z :
+ - inven,secondary_negate_x :
+ - inven,secondary_negate_y :
+ - inven,secondary_negate_z :
+ - inven,aux_type :
+ - inven,aux_name :
+ - inven,aux_reg :
+ - inven,read_only_slave_type :
+ - inven,read_only_slave_name :
+ - inven,read_only_slave_reg :
+
+Example:
+	iam20680@69 {
+		compatible = "inven,iam20680";
+		reg = <0x69>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&int1_default>;
+		interrupt-parent = <&tlmm_pinmux>;
+		interrupts = <78 IRQ_TYPE_EDGE_RISING>;
+		inven,vdd_ana-supply = <&pm8941_l17>;
+		inven,vcc_i2c-supply = <&pm8941_lvs1>;
+		inven,gpio_int1 = <&msmgpio 73 0x00>;
+		axis_map_x = <1>;
+		axis_map_y = <0>;
+		axis_map_z = <2>;
+		negate_x = <1>;
+		negate_y = <0>;
+		negate_z = <0>;
+		fs_range = <0x00>;
+		poll_interval = <200>;
+		min_interval = <5>;
+		inven,secondary_reg = <0x0c>;
+		/* If no compass sensor,
+		 * replace "compass" with "none"
+		 */
+		inven,secondary_type = "compass";
+		inven,secondary_name = "ak09911";
+		inven,secondary_axis_map_x = <1>;
+		inven,secondary_axis_map_y = <0>;
+		inven,secondary_axis_map_z = <2>;
+		inven,secondary_negate_x = <1>;
+		inven,secondary_negate_y = <1>;
+		inven,secondary_negate_z = <1>;
+		/* If no pressure sensor,
+		 * replace "pressure" with "none"
+		 */
+		inven,aux_type = "pressure";
+		inven,aux_name = "bmp280";
+		inven,aux_reg = <0x76>;
+		/* If no ALS sensor
+		 * replace "als" with "none"
+		 */
+		inven,read_only_slave_type = "als";
+		inven,read_only_slave_name = "apds9930";
+		inven,read_only_slave_reg = <0x39>;
+	};
diff --git a/Documentation/devicetree/bindings/iio/imu/st-asm330.txt b/Documentation/devicetree/bindings/iio/imu/st-asm330.txt
new file mode 100644
index 0000000..3833d59
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/st-asm330.txt
@@ -0,0 +1,44 @@
+The ASM330 is a highly integrated, low power inertial measurement unit (IMU)
+that provides precise acceleration and angular rate (gyroscopic) measurement.
+
+To enable driver probing, add the asm330lhh node to the platform device tree as described below.
+
+Required properties:
+
+- compatible: "st,asm330lhh"
+- reg: the I2C address or SPI chip select the device will respond to
+- interrupt-parent: phandle to the parent interrupt controller as documented in [interrupts][4]
+- interrupts: interrupt mapping for IRQ as documented in [interrupts][4]
+
+Recommended properties for SPI bus usage:
+- spi-max-frequency: maximum SPI bus frequency as documented in [SPI][3]
+
+Optional properties:
+- st,drdy-int-pin: MEMS sensor interrupt line to use (default 1)
+
+I2C example (based on Raspberry PI 3):
+
+	&i2c0 {
+		status = "ok";
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+		asm330lhh@6b {
+			compatible = "st,asm330lhh";
+			reg = <0x6b>;
+			interrupt-parent = <&gpio>;
+			interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+		};
+
+SPI example (based on Raspberry PI 3):
+
+	&spi0 {
+		status = "ok";
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+		asm330lhh@0 {
+			spi-max-frequency = <500000>;
+			compatible = "st,asm330lhh";
+			reg = <0>;
+			interrupt-parent = <&gpio>;
+			interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+		};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/maxim-sti.txt b/Documentation/devicetree/bindings/input/touchscreen/maxim-sti.txt
new file mode 100644
index 0000000..c0f29f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/maxim-sti.txt
@@ -0,0 +1,48 @@
+Maxim STI touch controller:
+
+Required properties:
+- spi-max-frequency: Maximum SPI frequency supported by the controller.
+- avdd-supply: analog power supply.
+- dvdd-supply: digial power supply.
+- maxim_sti,irq-gpio: irq gpio.
+- maxim_sti,reset-gpio: reset gpio.
+- maxim_sti,touch_fusion: path to touch_fusion daemon.
+- maxim_sti,config_file: path to config file.
+- maxim_sti,fw_name: name of firmware file.
+
+Optional properties:
+ - pinctrl-names	: this should be defined if a target uses pinctrl framework.
+			See "pinctrl" in documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
+			It should specify the names of the configs that pinctrl can install in driver.
+			Following are the pinctrl configs that can be installed:
+			"pmx_ts_active" : active configuration of pins. This should specify active
+			config defined in pin groups of interrupt and reset gpios.
+			"pmx_ts_suspend" : disabled configuration of pins. This should specify sleep
+			config defined in pin groups of interrupt and reset gpios.
+ - maxim_sti,mt_type_b_enabled	: Boolean type. This should be used to enable type B multitouch protocol.
+Example:
+
+&spi_13 { /* BLSP1 QUP3 */
+	status = "ok";
+	maxim_sti@0 {
+		compatible = "maxim,maxim_sti";
+		reg = <0>;
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <65 0>;
+		spi-max-frequency = <16000000>;
+		avdd-supply = <&pm8950_l17>;
+		dvdd-supply = <&pm8950_l6>;
+		spi-supply = <&pm8950_l5>;
+		maxim_sti,irq-gpio = <&msm_gpio 65 0x00>;
+		maxim_sti,reset-gpio = <&msm_gpio 64 0x00>;
+		maxim_sti,touch_fusion = "/vendor/bin/touch_fusion";
+		maxim_sti,config_file = "/vendor/firmware/touch_fusion_panel_id_0x%04x.cfg";
+		maxim_sti,fw_name = "maxim_fp35.bin";
+		maxim_sti,mt_type_b_enabled;
+		pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release";
+		pinctrl-0 = <&ts_int_active &ts_reset_active>;
+		pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+		pinctrl-2 = <&ts_release>;
+       };
+};
+
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
index 59651a3..6ccf98e 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
@@ -711,6 +711,59 @@
   Definition: This property is required if the clk is shared clk between different
 	sensor and ois, if this device need to be opened together.
 
+=============================
+IRLED MODULE
+=============================
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,camera-ir-led".
+
+- cell-index: cci hardware core index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the Hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: offset and length of the register set
+	for the device for the cci operating in
+	compatible mode.
+
+- pinctrl-names
+  Usage: required
+  Value type: <string>
+  Definition: List of names to assign the shared pin state defined in pinctrl device node
+
+- pinctrl-<0..n>
+  Usage: required
+  Value type: <phandle>
+  Definition: Lists phandles each pointing to the pin configuration node within a pin
+
+- gpios
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain phandle to gpio controller node and array of
+	#gpio-cells specifying specific gpio (controller specific)
+
+- gpio-req-tbl-num
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio table index.
+
+- gpio-req-tbl-flags
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio functions.
+
+- gpio-req-tbl-label
+  Usage: required
+  Value type: <string>
+  Definition: should specify the gpio labels in
+	gpio-req-tbl-num property (in the same order)
+
 Example:
 &soc {
     led_flash0: qcom,camera-flash@0 {
@@ -721,6 +774,32 @@
          switch-source = <&pmi8998_switch>;
          status = "ok";
     };
+
+    ir_led: qcom,camera-ir-led@0 {
+        cell-index = <0>;
+        reg = <0x00>;
+        compatible = "qcom,camera-ir-led";
+        enable-active-high;
+
+        gpio-no-mux = <0>;
+        pinctrl-names = "cam_default", "cam_suspend";
+        pinctrl-0 = <&cam_sensor_ir_led_on>;
+        pinctrl-1 = <&cam_sensor_ir_led_off>;
+        gpios = <&tlmm 22 0>,
+                <&tlmm 141 0>,
+                <&tlmm 142 0>,
+                <&tlmm 107 0>,
+                <&tlmm 110 0>;
+        gpio-req-tbl-num = <0 1 2 3 4>;
+        gpio-req-tbl-flags = <0 0 0 0 0>;
+        gpio-req-tbl-label = "CAM_IR_LED",
+                             "CAM_IR_LED_CUR0",
+                             "CAM_IR_LED_CUR1",
+                             "CAM_IR_CUT1",
+                             "CAM_IR_CUT2";
+        status = "ok";
+    };
+
 };
 
 &cam_cci0 {
diff --git a/Documentation/devicetree/bindings/pci/msm_ep_pcie.txt b/Documentation/devicetree/bindings/pci/msm_ep_pcie.txt
index 6026756..138fb7e 100644
--- a/Documentation/devicetree/bindings/pci/msm_ep_pcie.txt
+++ b/Documentation/devicetree/bindings/pci/msm_ep_pcie.txt
@@ -4,7 +4,8 @@
   - compatible: should be "qcom,pcie-ep".
   - reg: should contain PCIe register maps.
   - reg-names: indicates various resources passed to driver by name.
-		Should be "msi", "dm_core", "elbi", "parf", "phy", "mmio".
+		Should be "msi", "dm_core", "elbi", "parf", "phy", "mmio",
+		"tcsr_pcie_perst_en".
 		These correspond to different modules within the PCIe domain.
   - #address-cells: Should provide a value of 0.
   - interrupt-parent: Should be the PCIe device node itself here.
@@ -77,8 +78,11 @@
 			<0xbffff000 0x1000>,
 			<0xfc520000 0x2000>,
 			<0xfc526000 0x1000>,
-			<0xfc527000 0x1000>;
-		reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio";
+			<0xfc527000 0x1000>,
+			<0x01fcb000 0x1000>;
+
+		reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio",
+				"tcsr_pcie_perst";
 
 		#address-cells = <0>;
 		interrupt-parent = <&pcie_ep>;
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index 1e49e96..d8e459b 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -308,6 +308,11 @@
 	Definition: Boolean property to support external-rsense based
 		    configuration.
 
+- qcom,qg-vbms-mode
+	Usage:      optional
+	Value type: <bool>
+	Definition: Boolean property to run QG in Voltage-only mode of QG.
+
 - qcom,shutdown-temp-diff
 	Usage:      optional
 	Value type: <u32>
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
index 8b2234e..326f279 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
@@ -13,12 +13,15 @@
 
 Optional Properties:
 
-- interrupts			This indicates the IRQ number of the GPIO
-				connected to the STAT pin.
+- interrupts			This indicates the IRQ numbers of the GPIOs
+				connected to the STAT and usb-id pins.
+- interrupt-names		The irq names should be smb1360_stat_irq and
+				smb1360_usb_id_irq.The stat irq is mandatory
+				and usb_id irq is optional.
 - pinctrl-names:		The state name of the pin configuration. Only
 				support: "default".
-- pinctrl-0:			The phandle of the pin configuration node in
-				pinctrl for smb_int_pin.
+- pinctrl-0:			The phandles of the pin configuration node in
+				pinctrl for smb_int_pin and usb-id pin.
 				For details of pinctrl properties, please refer to:
 				"Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt"
 - qcom,float-voltage-mv	 	Float Voltage in mV - the maximum voltage up to which
@@ -177,6 +180,8 @@
 				Please go through the documentation for PMIC gpio
 				configuration details:
 				Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+- qcom,usb-id-gpio		GPIO for usb-id detection.This property is mandatory
+				if usb-id irq is specified.
 - qcom,parallel-charging-enabled: A bool property which enables SMB1360 to
 				operate in the parallel mode. SMB1360 acts
 				as the primary charger.
@@ -192,9 +197,13 @@
 			compatible = "qcom,smb1360-chg-fg";
 			reg = <0x1b>;
 			interrupt-parent = <&spmi_bus>;
-			interrupts = <0x00 0xcd 0>;
+			interrupts = <0x00 0xcd 0>,
+					<0 0xc3 0 3>;
+			interrupt-names = "smb1360_stat_irq",
+					"smb1360_usb_id_irq";
 			pinctrl-names = "default";
-			pinctrl-0 = <&smb_int_default>;
+			pinctrl-0 = <&smb_int_default>,
+					<&usb_id_default>;
 
 			/* battery-profile selection properties */
 			qcom,batt-profile-select;
@@ -242,5 +251,6 @@
 
 			qcom,otg-fet-present;
 			qcom,otg-fet-enable-gpio = <&pm8916_gpios 3 0>;
+			qcom,usb-id-gpio = <&pm8916_gpios 4 0>;
 		};
 	};
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
index 748cfbe..06efe49 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
@@ -39,6 +39,12 @@
 		     to be enabled only on platforms where voltage needs to
 		     be ramped up with multiple steps.
 
+- qcom,pwrdn-delay-ms
+	Usage:      optional
+	Value type: <u32>
+	Definition:  Required to control the LDO power down delay.
+		     Possible values are 0, 1, 4, 8.
+
 Touch-to-wake (TTW) properties:
 
 TTW supports 2 modes of operation - HW and SW. In the HW mode the enable/disable
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index c517d3c..0615f87 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1406,6 +1406,197 @@
 					  "SpkrRight", "SpkrLeft";
 	};
 
+* MSM8909 ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,msm8909-audio-codec"
+- qcom,model : The user-visible name of this sound card.
+- reg : Offset and length of the register region(s) for MI2S/PCM MUX
+- reg-names : Register region name(s) referenced in reg above
+	 Required register resource entries are:
+	 "csr_gp_io_mux_mic_ctl": Physical address of MUX that controls
+				controls LPA IF tertiary, quad, PCM0, Digital Codec
+				and Secondary TLMM mux setting for mic path operation.
+	 "csr_gp_io_mux_spkr_ctl": Physical address of MUX that controls
+				IF primary, secondary, Digital Codec and Primary TLMM
+				setting for speaker path operation.
+	 "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel": Physical address of MUX
+				that controls the mux between LPA IF Quad and PCM0
+				path to secondary TLMM
+- qcom,msm-hs-micbias-type : This property is used to recognize the headset
+  micbias type, internal or external.
+- qcom,msm-ext-pa : This property is used to inform machine driver about
+  the connection of external PA over available MI2S interfaces,
+  following values can be given to this property.
+  primary -> Primary MI2S interface
+  secondary -> Secondary MI2S interface
+  tertiary -> Tertiary MI2S interface
+  quaternary -> Quaternary MI2S interface
+- qcom,msm-mbhc-hphl-swh: This property is used to distinguish headset HPHL
+switch type on target typically the switch type will be normally open or
+normally close, value for this property 0 for normally close and 1 for
+normally open.
+-  qcom,msm-mbhc-gnd-swh: This property is used to distinguish headset GND
+switch type on target typically the switch type will be normally open or
+normally close, value for this property 0 for normally close and 1 for
+normally open.
+- qcom,audio-routing : A list of the connections between audio components.
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+
+Optional properties:
+- qcom,msm-afe-clk-ver: Provides detail of AFE clock API version.
+- qcom,hdmi-dba-codec-rx: Boolean. specifies if HDMI DBA audio support is enabled or not.
+- qcom,split-a2dp: Boolean. specifies if split a2dp audio support is enabled or not.
+- qcom,prim-auxpcm-gpio-clk  : GPIO on which Primary AUXPCM clk signal is coming.
+- qcom,prim-auxpcm-gpio-sync : GPIO on which Primary AUXPCM SYNC signal is coming.
+- qcom,prim-auxpcm-gpio-din  : GPIO on which Primary AUXPCM DIN signal is coming.
+- qcom,prim-auxpcm-gpio-dout : GPIO on which Primary AUXPCM DOUT signal is coming.
+- qcom,prim-auxpcm-gpio-set : set of GPIO lines used for Primary AUXPCM port
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,msm-micbias1-ext-cap : Boolean. Enable micbias1 external
+capacitor mode.
+- qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external
+capacitor mode.
+- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa.
+- qcom,subsys-name: This value provides the subsystem name where codec
+		is present. This property enables the codec driver to
+		register and receive subsytem restart notification from subsystem
+		and follow appropriate steps to ensure codec is in proper state
+		after subsytem restart. By default codec driver register
+		with ADSP subsystem.
+
+To Configure External Audio Switch
+- qcom,msm-ext-audio-switch : GPIO which controls external switch that switches
+  audio path between headset and speakers.
+- ext-switch-vdd-supply : Power supply that control external audio switch
+- qcom,ext-switch-vdd-voltage : Minimum and maximum voltage in uV to set for
+  power supply.
+- qcom,ext-switch-vdd-op-mode : Maxmum # of uA current the switch will draw
+  from the power supply.
+Example:
+	qcom,msm-ext-audio-switch = <&msm_gpio 2 0>; - gpio # and active_state
+	ext-switch-vdd-supply = <&pm8950_l13>; - Power Rail
+	qcom,ext-switch-vdd-voltage = <3075000 3075000>; - Min, Max uV voltage
+	qcom,ext-switch-vdd-op-mode = <5000>; - Operational current uA
+	Additional needs to add two additional qcom,audio-routings
+			"HEADPHONE", "VDD_EXT_AUDIO_SWITCH"
+			"SPK_OUT", "VDD_EXT_AUDIO_SWITCH"
+
+- qcom,msm-mclk-freq : This property is used to inform machine driver about
+mclk frequency needs to be configured for internal and external PA.
+- asoc-platform: This is phandle list containing the references to platform device
+		 nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+		       the platform names should match to that of the phandle order
+		       given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+	    that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+		  cpu dai names should match to that of the phandle order given.
+- asoc-codec: This is phandle list containing the references to codec dai device
+	nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+	codec dai names should match to that of the phandle order given
+	in "asoc-codec".
+- asoc-wsa-codec-names: This property contains list of wsa codec names. The names
+		  should comply with the wsa nodes configurations.
+- asoc-wsa-codec-prefixes: This property contains list of wsa codec prefixes.
+- msm-vdd-wsa-switch-supply: WSA codec supply's regulator device tree node.
+- qcom,msm-vdd-wsa-switch-voltage: WSA codec supply's voltage level in mV.
+- qcom,msm-vdd-wsa-switch-current: WSA codec max current level in mA.
+
+Example:
+	 sound {
+		compatible = "qcom,msm8909-audio-codec";
+		qcom,model = "msm8909-snd-card";
+		reg = <0xc051000 0x4>,
+		      <0xc051004 0x4>,
+		      <0xc055000 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			    "csr_gp_io_mux_spkr_ctl",
+			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel";
+		qcom,msm-afe-clk-ver = <1>;
+		qcom,msm-ext-pa = "primary";
+		qcom,hdmi-dba-codec-rx;
+		qcom,split-a2dp;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-hs-micbias-type = "internal";
+		qcom,msm-micbias1-ext-cap;
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"SPK_RX_BIAS", "MCLK",
+			"INT_LDO_H", "MCLK",
+			"MIC BIAS External", "Handset Mic",
+			"MIC BIAS Internal2", "Headset Mic",
+			"MIC BIAS External", "Secondary Mic",
+			"AMIC1", "MIC BIAS External",
+			"AMIC2", "MIC BIAS Internal2",
+			"AMIC3", "MIC BIAS External";
+		qcom,msm-gpios =
+			"pri_i2s",
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"us_eu_gpio_act",
+			"pri_i2s_us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"us_eu_gpio_act",
+			"pri_i2s_us_eu_gpio_act";
+		pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus &cross_conn_det_sus>;
+		pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act &cross_conn_det_sus>;
+		pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus &cross_conn_det_act>;
+		pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act &cross_conn_det_act>;
+		qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>;
+		qcom,prim-auxpcm-gpio-clk  = <&msm_gpio 63 0>;
+		qcom,prim-auxpcm-gpio-sync = <&msm_gpio 64 0>;
+		qcom,prim-auxpcm-gpio-din  = <&msm_gpio 65 0>;
+		qcom,prim-auxpcm-gpio-dout = <&msm_gpio 66 0>;
+		qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
+		qcom,tapan-codec-9302;
+		asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&lpa>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe",
+				"msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa";
+		asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>,
+				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+				<&bt_sco_rx>, <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>,
+				<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>,
+				<&incall_music_2_rx>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+				"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+				"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+				"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+				"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+		asoc-codec = <&stub>, <&pm8916_tombak_dig>;
+		asoc-codec-names = "msm-stub-codec.1", "tombak_codec";
+		asoc-wsa-codec-names = "wsa881x-i2c-codec.8-000f";
+		asoc-wsa-codec-prefixes = "SpkrMono";
+	};
+
 * MSM8952 ASoC Machine driver
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index ed51a77..fa8b60e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -319,3 +319,4 @@
 zii	Zodiac Inflight Innovations
 zte	ZTE Corp.
 zyxel	ZyXEL Communications Corp.
+inven   InvenSense, Inc.
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-blsp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-blsp.dtsi
index 13e1fc3..f0078a8 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-blsp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-blsp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017, 2019, 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
@@ -128,7 +128,7 @@
 		status = "disabled";
 	};
 
-	i2c_5: i2c@835000 { /* BLSP1 QUP1: GPIO: 74,75 */
+	i2c_5: i2cb@835000 { /* BLSP1 QUP1: GPIO: 74,75 */
 		compatible = "qcom,i2c-msm-v2";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -151,7 +151,7 @@
 		status = "disabled";
 	};
 
-	i2c_6: i2c@836000 { /* BLSP1 QUP2: GPIO: 65,66 */
+	i2c_6: i2cb@836000 { /* BLSP1 QUP2: GPIO: 65,66 */
 		compatible = "qcom,i2c-msm-v2";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -174,7 +174,7 @@
 		status = "disabled";
 	};
 
-	i2c_7: i2c@838000 { /* BLSP1 QUP4: GPIO: 18,19 */
+	i2c_7: i2cb@838000 { /* BLSP1 QUP4: GPIO: 18,19 */
 		compatible = "qcom,i2c-msm-v2";
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi
index 1428f37..ba73271 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi
@@ -37,3 +37,7 @@
 &mhi_device {
 	status = "okay";
 };
+
+&restart_pshold {
+	qcom,force-warm-reboot;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi
index 81877b7..57bd822 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi
@@ -31,3 +31,7 @@
 &mhi_device {
 	status = "okay";
 };
+
+&restart_pshold {
+	qcom,force-warm-reboot;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi
index d7c0d13..1f99451 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi
@@ -37,3 +37,7 @@
 &mhi_device {
 	status = "okay";
 };
+
+&restart_pshold {
+	qcom,force-warm-reboot;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi
index 6ceac6e..d8edfde 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi
@@ -31,3 +31,7 @@
 &mhi_device {
 	status = "okay";
 };
+
+&restart_pshold {
+	qcom,force-warm-reboot;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index c167bdd..410d9d0 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -1699,6 +1699,58 @@
 				};
 			};
 		};
+
+		sensor_int1_default: sensor_int1_default {
+			     mux {
+				     pins = "gpio78";
+				     function = "gpio";
+			     };
+
+			     config {
+				     pins = "gpio78";
+				     drive-strength = <16>; /* 16 mA */
+				     bias-pull-down; /* pull down */
+			     };
+		};
+
+		sensor_int2_default: sensor_int2_default {
+			     mux {
+				     pins = "gpio79";
+				     function = "gpio";
+			     };
+
+			     config {
+				     pins = "gpio79";
+				     drive-strength = <16>; /* 16 mA */
+				     bias-pull-down; /* pull down */
+			     };
+		};
+
+		pinctrl_pps: ppsgrp {
+			mux {
+				pins = "gpio42";
+				function = "nav_dr";
+			};
+
+			config {
+				pins = "gpio42";
+				bias-pull-down;
+			};
+		};
+
+		pmx_can_reset: pmx_can_reset {
+			mux {
+				pins = "gpio99";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio99";
+				drive-strength = <2>;
+				bias-disable;
+				output-high;
+			};
+		};
 	};
 };
 
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
index fa8f3a4..d850853 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -21,3 +21,65 @@
 	qcom,connector-type-uAB;
 	extcon = <0>, <0>, <0>, <&vbus_detect>;
 };
+
+&soc {
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	vreg_can: vreg_can {
+		compatible = "regulator-fixed";
+		regulator-name = "vreg_can";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		enable-active-high;
+		gpio = <&tlmm 71 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&i2c_4 {
+	status = "okay";
+
+	iam20680@69 {
+	       compatible = "inven,iam20680";
+	       reg = <0x69>;
+	       pinctrl-names = "default";
+	       pinctrl-0 = <&sensor_int1_default>;
+	       interrupt-parent = <&tlmm>;
+	       interrupts = <78 IRQ_TYPE_EDGE_RISING>;
+	       axis_map_x = <1>;
+	       axis_map_y = <0>;
+	       axis_map_z = <2>;
+	       negate_x = <1>;
+	       negate_y = <0>;
+	       negate_z = <0>;
+	       inven,secondary_type = "none";
+	       inven,aux_type = "none";
+	       inven,read_only_slave_type = "none";
+	};
+
+	asm330@6a {
+	       compatible = "st,asm330lhh";
+	       reg = <0x6a>;
+	       pinctrl-names = "default";
+	       pinctrl-0 = <&sensor_int1_default>;
+	       interrupt-parent = <&tlmm>;
+	       interrupts = <78 IRQ_TYPE_EDGE_RISING>;
+	       st,drdy-int-pin= <2>;
+	};
+};
+
+&spi_2 {
+	status = "okay";
+};
+
+&tlmm {
+	/* Set these up as hogs */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pmx_can_reset>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index aa67cdb..aa048de 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -363,9 +363,10 @@
 			<0x40001000 0x1000>,
 			<0x01c00000 0x2000>,
 			<0x01c02000 0x1000>,
-			<0x01c04000 0x1000>;
+			<0x01c04000 0x1000>,
+			<0x01fcb000 0x1000>;
 		reg-names = "msi", "dm_core", "elbi", "iatu", "parf",
-				"phy", "mmio";
+				"phy", "mmio", "tcsr_pcie_perst_en";
 
 		#address-cells = <0>;
 		interrupt-parent = <&pcie_ep>;
@@ -619,7 +620,7 @@
 		clock-frequency = <32768>;
 	};
 
-	restart@c264000 {
+	restart_pshold: restart@c264000 {
 		compatible = "qcom,pshold";
 		reg = <0x0c264000 0x4>,
 			<0x01fd3000 0x4>;
@@ -1306,6 +1307,7 @@
 		compatible = "qcom,cnss_sdio";
 		subsys-name = "AR6320_SDIO";
 		vdd-wlan-supply = <&vreg_wlan>;
+		vdd-wlan-xtal-supply = <&pmxpoorwills_l5>;
 		vdd-wlan-io-supply = <&pmxpoorwills_l6>;
 		qcom,wlan-ramdump-dynamic = <0x200000>;
 		pinctrl-names = "active", "sleep";
@@ -1313,6 +1315,8 @@
 		pinctrl-1 = <&cnss_sdio_sleep>;
 		qcom,is-antenna-shared;
 		status = "disabled";
+		vdd-wlan-xtal-min = <1704000>;
+		vdd-wlan-xtal-max = <1704000>;
 	};
 };
 
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 13d07d2..c9157c4 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -215,6 +215,7 @@
 CONFIG_IPC_ROUTER=y
 CONFIG_IPC_ROUTER_SECURITY=y
 CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_REGMAP_SND_DIGCDC=y
 CONFIG_DMA_CMA=y
 CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 56ae8fa..7a02588 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -214,6 +214,7 @@
 CONFIG_IPC_ROUTER=y
 CONFIG_IPC_ROUTER_SECURITY=y
 CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_REGMAP_SND_DIGCDC=y
 CONFIG_DMA_CMA=y
 CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/arm/configs/sdxpoorwills-auto-perf_defconfig b/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
index f26242f..d28debf 100644
--- a/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
@@ -214,6 +214,7 @@
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
 CONFIG_PPP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPP_ASYNC=y
@@ -255,6 +256,7 @@
 CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PPS_CLIENT_GPIO=y
 CONFIG_PTP_1588_CLOCK=y
 CONFIG_PINCTRL_SDXPOORWILLS=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@ -326,6 +328,7 @@
 CONFIG_USB_GADGET_VBUS_DRAW=500
 CONFIG_USB_CONFIGFS=y
 CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_RNDIS=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
@@ -334,6 +337,7 @@
 CONFIG_USB_CONFIGFS_F_CDEV=y
 CONFIG_USB_CONFIGFS_F_GSI=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_USB_CONFIGFS_F_IPC=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_PARANOID_SD_INIT=y
@@ -392,6 +396,7 @@
 CONFIG_TRACER_PKT=y
 CONFIG_QTI_RPMH_API=y
 CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_USB_XPRT=y
 CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_GLINK_PKT=y
@@ -412,8 +417,10 @@
 CONFIG_INV_MPU_IIO_IAM20680=y
 CONFIG_INV_MPU_IIO_I2C=y
 CONFIG_INV_MPU_IIO_SPI=y
+CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING=y
 CONFIG_INV_TESTING=y
 CONFIG_IIO_ST_ASM330LHH=y
+CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
 CONFIG_QCOM_SHOW_RESUME_IRQ=y
diff --git a/arch/arm/configs/sdxpoorwills-auto_defconfig b/arch/arm/configs/sdxpoorwills-auto_defconfig
index 705a560..a850974 100644
--- a/arch/arm/configs/sdxpoorwills-auto_defconfig
+++ b/arch/arm/configs/sdxpoorwills-auto_defconfig
@@ -208,6 +208,7 @@
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
 CONFIG_PPP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPP_ASYNC=y
@@ -250,9 +251,11 @@
 CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PPS_CLIENT_GPIO=y
 CONFIG_PTP_1588_CLOCK=y
 CONFIG_PINCTRL_SDXPOORWILLS=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
@@ -327,6 +330,7 @@
 CONFIG_USB_GADGET_VBUS_DRAW=500
 CONFIG_USB_CONFIGFS=y
 CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_RNDIS=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
@@ -335,6 +339,7 @@
 CONFIG_USB_CONFIGFS_F_CDEV=y
 CONFIG_USB_CONFIGFS_F_GSI=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_USB_CONFIGFS_F_IPC=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_RING_BUFFER=y
@@ -397,6 +402,7 @@
 CONFIG_TRACER_PKT=y
 CONFIG_QTI_RPMH_API=y
 CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_USB_XPRT=y
 CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_GLINK_PKT=y
@@ -417,8 +423,10 @@
 CONFIG_INV_MPU_IIO_IAM20680=y
 CONFIG_INV_MPU_IIO_I2C=y
 CONFIG_INV_MPU_IIO_SPI=y
+CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING=y
 CONFIG_INV_TESTING=y
 CONFIG_IIO_ST_ASM330LHH=y
+CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
 CONFIG_QCOM_SHOW_RESUME_IRQ=y
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index fb236fc..f7e8451 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -337,6 +337,7 @@
 
 ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
 dtbo-$(CONFIG_ARCH_MSM8940) += msm8940-mtp-overlay.dtbo
+dtbo-$(CONFIG_ARCH_MSM8940) += msm8940-cdp-overlay.dtbo
 
 dtbo-$(CONFIG_ARCH_MSM8917) += msm8917-mtp-overlay.dtbo \
 	msm8917-qrd-overlay.dtbo \
@@ -349,6 +350,7 @@
 	apq8017-cdp-wcd-rome-overlay.dtbo
 
 dtbo-$(CONFIG_ARCH_QM215) +=qm215-qrd-overlay.dtbo
+dtbo-$(CONFIG_ARCH_QM215) +=qm215-qrd-smb1360-overlay.dtbo
 
 dtbo-$(CONFIG_ARCH_MSM8953) += msm8953-mtp-overlay.dtbo \
 	msm8953-cdp-overlay.dtbo \
@@ -392,6 +394,10 @@
 	msm8940-pmi8937.dtb \
 	msm8940-pmi8940.dtb
 
+msm8940-cdp-overlay.dtbo-base := msm8940-pmi8950.dtb \
+	msm8940-pmi8937.dtb \
+	msm8940-pmi8940.dtb
+
 msm8917-mtp-overlay.dtbo-base := msm8917-pmi8950.dtb \
 	msm8917-pmi8937.dtb \
 	msm8917-pmi8940.dtb
@@ -421,6 +427,7 @@
 	apq8017-pmi8937.dtb
 
 qm215-qrd-overlay.dtbo-base := qm215.dtb
+qm215-qrd-smb1360-overlay.dtbo-base := qm215.dtb
 
 msm8953-mtp-overlay.dtbo-base := sdm450.dtb \
 	msm8953.dtb \
@@ -560,6 +567,7 @@
 	msm8917-pmi8940-rcm.dtb
 
 dtb-$(CONFIG_ARCH_QM215) += qm215-qrd.dtb
+dtb-$(CONFIG_ARCH_QM215) += qm215-qrd-smb1360.dtb
 
 dtb-$(CONFIG_ARCH_MSM8909) += msm8909-pm8916-mtp.dtb \
 	sdw3100-msm8909w-wtp.dtb \
@@ -571,7 +579,10 @@
 	apq8009-robot-pronto-refboard.dtb \
 	apq8009-dragon.dtb \
 	apq8009-lat-v1.0.dtb \
-	sdw3100-msm8909w-1gb-wtp.dtb
+	sdw3100-msm8909w-1gb-wtp.dtb \
+	sdw2500-apq8009w-wtp.dtb \
+	sdw2500-msm8909w-wtp.dtb
+
 
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
@@ -611,7 +622,8 @@
 	sda439-cdp.dtb \
 	sdm439-external-codec-mtp.dtb \
 	sdm439-rcm.dtb \
-	qm215-qrd.dtb
+	qm215-qrd.dtb \
+	qm215-qrd-smb1360.dtb
 
 dtb-$(CONFIG_ARCH_SDM429) += sdm429-mtp.dtb \
 	sdm429-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8009w-memory.dtsi
new file mode 100644
index 0000000..fbac238
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009w-memory.dtsi
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2019, 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.
+ */
+
+&external_image_mem {
+	reg = <0x0 0x87b00000 0x0 0x0500000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x02100000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x8a100000 0x0 0x0600000>;
+};
+
+&reserved_mem {
+	linux,cma {
+		compatible = "shared-dma-pool";
+		alloc-ranges = <0 0x00000000 0 0xa0000000>;
+		reusable;
+		alignment = <0 0x400000>;
+		size = <0 0x1000000>;
+		linux,cma-default;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi
index 87a5253..e69d7d4 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -94,7 +94,7 @@
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
-		qcom,mdss-dsi-reset-sequence = <1 20>, <0 20>, <1 20>;
+		qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>;
 		/* clk = totlaH * totalV * bpp* 66fps */
 		qcom,mdss-dsi-panel-clockrate = <276705792>;
 		qcom,esd-check-enabled;
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index a4e64fb..01f1790 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, 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
@@ -474,6 +474,16 @@
 		clock-names = "core", "iface";
 	};
 
+	blsp1_uart2: serial@78b0000 {
+		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uart";
+		reg = <0x78b0000 0x200>;
+		interrupts = <0 108 0>;
+		status = "disabled";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+			 <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		clock-names = "core", "iface";
+	};
+
 	blsp1_uart2_hs: uart@78b0000 {		/*BLSP1 UART2*/
 		compatible = "qcom,msm-hsuart-v14";
 		reg = <0x78b0000 0x200>,
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-memory.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-memory.dtsi
new file mode 100644
index 0000000..fd5df15
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909w-memory.dtsi
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2019, 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.
+ */
+
+&external_image_mem {
+	reg = <0x0 0x87b00000 0x0 0x0500000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x05000000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x8d000000 0x0 0x0600000>;
+};
+
+&reserved_mem {
+	linux,cma {
+		compatible = "shared-dma-pool";
+		alloc-ranges = <0 0x00000000 0 0xa0000000>;
+		reusable;
+		alignment = <0 0x400000>;
+		size = <0 0x1000000>;
+		linux,cma-default;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
index 5c63ed3..7c0d323 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
@@ -120,7 +120,7 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-		input-name = "gpio-keys";
+		label = "gpio-keys";
 		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
 
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index 2118140..e1ec685 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -491,6 +491,12 @@
 			< 1401000000 4>,
 			< 1497600000 5>;
 
+		qcom,speed2-bin-v0-c1 =
+			<          0 0>,
+			<  960000000 1>,
+			< 1094400000 2>,
+			< 1209600000 3>;
+
 		qcom,speed3-bin-v0-c1 =
 			<          0 0>,
 			<  960000000 1>,
@@ -513,6 +519,7 @@
 		qcom,cpufreq-table =
 			 <  960000 >,
 			 < 1094400 >,
+			 < 1209600 >,
 			 < 1248000 >,
 			 < 1305600 >,
 			 < 1401000 >,
diff --git a/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi
new file mode 100644
index 0000000..46e480e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2015-2016, 2018-2019, 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 <dt-bindings/clock/msm-clocks-8952.h>
+
+&soc {
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+		pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+		pinctrl-0 = <&gpio_key_active>;
+		pinctrl-1 = <&gpio_key_suspend>;
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&tlmm 128 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			debounce-interval = <15>;
+		};
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&tlmm 127 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&tlmm 91 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			debounce-interval = <15>;
+		};
+
+		home {
+			label = "home";
+			gpios = <&tlmm 86 0x1>;
+			linux,input-type = <1>;
+			linux,code = <102>;
+			debounce-interval = <15>;
+		};
+	};
+
+	hbtp {
+		compatible = "qcom,hbtp-input";
+		vcc_dig-supply = <&pm8937_l5>;
+		qcom,dig-load = <15000>;
+		qcom,dig-vtg-min = <1800000>;
+		qcom,dig-vtg-max = <1800000>;
+	};
+};
+
+&tlmm {
+	tlmm_gpio_key {
+		gpio_key_active: gpio_key_active {
+			mux {
+				pins = "gpio86", "gpio91", "gpio127", "gpio128";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio86", "gpio91", "gpio127", "gpio128";
+			};
+		};
+
+		gpio_key_suspend: gpio_key_suspend {
+			mux {
+				pins = "gpio86", "gpio91", "gpio127", "gpio128";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio86", "gpio91", "gpio127", "gpio128";
+			};
+		};
+	};
+};
+
+&blsp1_uart2 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_active>;
+};
+
+&pmi_haptic{
+	qcom,wave-play-rate-us = <4165>;
+	qcom,lra-auto-res-mode="qwd";
+	qcom,lra-high-z="opt1";
+	qcom,lra-res-cal-period = <4>;
+	qcom,correct-lra-drive-freq;
+	qcom,misc-trim-error-rc19p2-clk-reg-present;
+};
+
+&sdhc_1 {
+	/* device core power supply */
+	vdd-supply = <&pm8937_l8>;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 570000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_l5>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 325000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on  &sdc1_rclk_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+								384000000>;
+	qcom,nonremovable;
+	qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	/* device core power supply */
+	vdd-supply = <&pm8937_l11>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 800000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_l12>;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 22000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+		1 &intc 0 221 0
+		2 &tlmm 67 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&tlmm 67 0x1>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+								200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	status = "ok";
+
+};
+
+&pm8937_gpios {
+	gpio@c400 {
+		qcom,mode = <0>;
+		qcom,output-type = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-sel = <0>;
+		qcom,master-en = <1>;
+		status = "okay";
+	};
+};
+
+&spi_3 { /* BLSP1 QUP3 */
+	maxim_sti@0 {
+		status = "disabled";
+		compatible = "maxim,maxim_sti";
+		reg = <0>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <65 0>;
+		spi-max-frequency = <16000000>;
+		avdd-supply = <&pm8937_l10>;
+		dvdd-supply = <&pm8937_l5>;
+		maxim_sti,irq-gpio = <&tlmm 65 0x00>;
+		maxim_sti,reset-gpio = <&tlmm 64 0x00>;
+		maxim_sti,touch_fusion = "/vendor/bin/touch_fusion";
+		maxim_sti,config_file = "/etc/firmware/qtc800s.cfg";
+		maxim_sti,fw_name = "qtc800s.bin";
+		pinctrl-names = "pmx_ts_active","pmx_ts_suspend",
+			"pmx_ts_release";
+		pinctrl-0 = <&ts_int_active &ts_reset_active>;
+		pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+		pinctrl-2 = <&ts_release>;
+	};
+};
+
+&i2c_5 { /* BLSP2 QUP1 */
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&tlmm 17 0x00>;
+		qcom,nq-ven = <&tlmm 16 0x00>;
+		qcom,nq-firm = <&tlmm 130 0x00>;
+		qcom,nq-clkreq = <&pm8937_gpios 5 0x00>;
+		interrupt-parent = <&tlmm>;
+		qcom,clk-src = "BBCLK2";
+		interrupts = <17 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active", "nfc_suspend";
+		pinctrl-0 = <&nfc_int_active &nfc_disable_active>;
+		pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+		clocks = <&clock_gcc clk_bb_clk2_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
+#include "msm8937-mdss-panels.dtsi"
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+	hw-config = "dual_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_truly_1080_vid>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-enable-gpio = <&tlmm 99 0>;
+	qcom,platform-reset-gpio = <&tlmm 60 0>;
+	qcom,platform-bklight-en-gpio = <&tlmm 98 0>;
+};
+
+&mdss_dsi1 {
+	qcom,dsi-pref-prim-pan = <&dsi_adv7533_1080p>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+	qcom,bridge-index = <0>;
+
+	qcom,pluggable;
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-enable-gpio = <&tlmm 99 0>;
+	qcom,platform-reset-gpio = <&tlmm 60 0>;
+	qcom,platform-bklight-en-gpio = <&tlmm 98 0>;
+};
+
+&dsi_truly_1080_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-min-refresh-rate = <48>;
+	qcom,mdss-dsi-max-refresh-rate = <60>;
+	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+};
+
+&dsi_truly_1080_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,ulps-enabled;
+	qcom,partial-update-enabled;
+	qcom,panel-roi-alignment = <2 2 4 2 1080 2>;
+};
+
+&dsi_truly_720_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8940-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8940-cdp-overlay.dts
new file mode 100644
index 0000000..141ef6c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8940-cdp-overlay.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "msm8937-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8940-PMI8950 CDP";
+	compatible = "qcom,msm8940-cdp", "qcom,msm8940", "qcom,cdp";
+	qcom,board-id= <1 0>;
+	qcom,msm-id = <313 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
index 1f0ad88..50dea91 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
@@ -27,7 +27,7 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-		input-name = "gpio-keys";
+		label = "gpio-keys";
 		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
 
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi
index 7ab5d1e..8472617 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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
@@ -12,10 +12,28 @@
  */
 
 &soc {
-	led_flash_rear: qcom,camera-flash@0 {
+	ir_led: qcom,camera-ir-led@0 {
 		cell-index = <0>;
-		reg = <0x00 0x00>;
-		compatible = "qcom,camera-flash";
+		reg = <0x00>;
+		compatible = "qcom,camera-ir-led";
+		enable-active-high;
+
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_ir_led_on>;
+		pinctrl-1 = <&cam_sensor_ir_led_off>;
+		gpios = <&tlmm 22 0>,
+			<&tlmm 141 0>,
+			<&tlmm 142 0>,
+			<&tlmm 107 0>,
+			<&tlmm 110 0>;
+		gpio-req-tbl-num = <0 1 2 3 4>;
+		gpio-req-tbl-flags = <0 0 0 0 0>;
+		gpio-req-tbl-label = "CAM_IR_LED",
+					"CAM_IR_LED_CUR0",
+					"CAM_IR_LED_CUR1",
+					"CAM_IR_CUT1",
+					"CAM_IR_CUT2";
 		status = "ok";
 	};
 };
@@ -34,7 +52,7 @@
 		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
 		sensor-position-yaw = <180>;
-		led-flash-src = <&led_flash_rear>;
+		ir-led-src = <&ir_led>;
 		cam_vio-supply = <&pm660_l11>;
 		cam_vana-supply = <&pm660_l15>;
 		cam_vdig-supply = <&pm660_l5>;
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
index 7e15752..7fcfd53 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
@@ -384,3 +384,7 @@
 &qupv3_se6_4uart {
 	status = "ok";
 };
+
+&apps_smmu {
+	/delete-property/ qcom,actlr;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 3c6c7a8..d119eeb 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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,52 +18,40 @@
 	qcom,msm-id = <347 0x0>;
 };
 
-&removed_region {
-	reg = <0 0x85fc0000 0 0x1540000>;
-};
-
-&pil_camera_mem {
-	reg = <0 0x8b800000 0 0x500000>;
-};
-
 &pil_modem_mem {
-	reg = <0 0x8bd00000 0 0x3100000>;
+	reg = <0 0x8b000000 0 0x3100000>;
 };
 
 &pil_video_mem {
-	reg = <0 0x8ee00000 0 0x500000>;
+	reg = <0 0x8e100000 0 0x500000>;
 };
 
 &wlan_msa_mem {
-	reg = <0 0x8f300000 0 0x100000>;
+	reg = <0 0x8e600000 0 0x100000>;
 };
 
 &pil_cdsp_mem {
-	reg = <0 0x8f400000 0 0x800000>;
+	reg = <0 0x8e700000 0 0x800000>;
 };
 
 &pil_mba_mem {
-	reg = <0 0x8fc00000 0 0x200000>;
+	reg = <0 0x8ef00000 0 0x200000>;
 };
 
 &pil_adsp_mem {
-	reg = <0 0x8fe00000 0 0x1e00000>;
+	reg = <0 0x8f100000 0 0x1e00000>;
 };
 
 &pil_ipa_fw_mem {
-	reg = <0 0x91c00000 0 0x10000>;
+	reg = <0 0x90f00000 0 0x10000>;
 };
 
 &pil_ipa_gsi_mem {
-	reg = <0 0x91c10000 0 0x5000>;
+	reg = <0 0x90f10000 0 0x5000>;
 };
 
 &pil_gpu_mem {
-	reg = <0 0x91c15000 0 0x2000>;
-};
-
-&qseecom_mem {
-	reg = <0 0x9e800000 0 0x1000000>;
+	reg = <0 0x90f15000 0 0x2000>;
 };
 
 &adsp_mem {
@@ -101,6 +89,10 @@
 	status = "disabled";
 };
 
+&sde_dp {
+	qcom,max-pclk-frequency-khz = <675000>;
+};
+
 &mem_dump {
 	rpmh {
 		qcom,dump-size = <0x400000>;
diff --git a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360-overlay.dts b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360-overlay.dts
new file mode 100644
index 0000000..2ada905
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360-overlay.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "qm215-qrd-smb1360.dtsi"
+
+/ {
+	model = "QRD + SMB1360";
+	qcom,board-id = <0x0b 5>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dts b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dts
new file mode 100644
index 0000000..c64753d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qm215.dtsi"
+#include "qm215-pm8916.dtsi"
+#include "qm215-qrd-smb1360.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. qm215 SMB1360 QRD";
+	compatible = "qcom,qm215-qrd", "qcom,qm215", "qcom,qrd";
+	qcom,board-id = <0x0b 5>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
new file mode 100644
index 0000000..3a802c7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
@@ -0,0 +1,81 @@
+/* Copyright (c) 2019, 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 "qm215-qrd.dtsi"
+
+&pm8916_chg{
+	qcom,use-external-charger;
+};
+
+&pm8916_bms{
+	qcom,disable-bms;
+};
+
+&tlmm {
+		/* SMB interrupt pin */
+		smb_int_pin {
+			smb_int_default: smb_int_default {
+				mux {
+					pins = "gpio13";
+					function ="gpio";
+				};
+				config {
+					pins = "gpio13";
+					bias-pull-up;           /* PULL UP*/
+					input-enable;
+				};
+			};
+		};
+};
+
+&pm8916_gpios {
+	usb_id {
+		usb_id_default: usb_id_default {
+			pins = "gpio4";
+			function = "normal";
+			input-enable;
+			bias-pull-up;
+			power-source = <0>;
+		};
+	};
+};
+
+&i2c_2 {
+	status ="ok";
+	smb1360_otg_supply: smb1360-chg-fg@14 {
+		compatible = "qcom,smb1360-chg-fg";
+		reg = <0x14>;
+		interrupts-extended = <&tlmm 13 8>,
+				<&spmi_bus 0 0xc3 0 3>;
+		interrupt-names = "smb1360_stat_irq",
+				"smb1360_usb_id_irq";
+		pinctrl-names = "default";
+		pinctrl-0 = <&smb_int_default>,
+			<&usb_id_default>;
+		qcom,empty-soc-disabled;
+		qcom,chg-inhibit-disabled;
+		qcom,float-voltage-mv = <4400>;
+		qcom,iterm-ma = <100>;
+		qcom,recharge-thresh-mv = <100>;
+		qcom,thermal-mitigation = <1500 700 600 0>;
+		qcom,fg-batt-capacity-mah = <2800>;
+		qcom,fg-cutoff-voltage-mv = <3400>;
+		qcom,fg-iterm-ma = <130>;
+		qcom,fg-delta-soc = <1>;
+		qcom,usb-id-gpio = <&pm8916_gpios 4 0>;
+		status= "okay";
+	};
+};
+
+&usb_otg {
+	extcon = <&smb1360_otg_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qm215.dtsi b/arch/arm64/boot/dts/qcom/qm215.dtsi
index 0589f45..36a8021 100644
--- a/arch/arm64/boot/dts/qcom/qm215.dtsi
+++ b/arch/arm64/boot/dts/qcom/qm215.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, 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
@@ -36,6 +36,10 @@
 	};
 };
 
+&clock_gcc {
+	compatible = "qcom,gcc-qm215";
+};
+
 /* GPU overrides */
 &msm_gpu {
 
diff --git a/arch/arm64/boot/dts/qcom/sda845.dtsi b/arch/arm64/boot/dts/qcom/sda845.dtsi
index aa9b733..3263ff8 100644
--- a/arch/arm64/boot/dts/qcom/sda845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017,2019, 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
@@ -16,3 +16,13 @@
 	model = "Qualcomm Technologies, Inc. SDA 845";
 	qcom,msm-id = <341 0x10000>;
 };
+
+&soc {
+	qcom,rmnet-ipa {
+		status="disabled";
+	};
+};
+
+&ipa_hw {
+	status="disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index 20562d1..4da0e52 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -127,7 +127,7 @@
 &soc {
 	gpio_keys {
 		compatible = "gpio-keys";
-		input-name = "gpio-keys";
+		label = "gpio-keys";
 		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
 
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index aa6b890..92eb4e8 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -2301,6 +2301,38 @@
 			};
 		};
 
+		cam_sensor_ir_led_on: cam_sensor_ir_led_on {
+			/*IR_LED*/
+			mux {
+				pins = "gpio22", "gpio141", "gpio142",
+						"gpio107", "gpio110";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio22", "gpio141", "gpio142",
+						"gpio107", "gpio110";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_ir_led_off: cam_sensor_ir_led_off {
+			/*IR_LED*/
+			mux {
+				pins = "gpio22", "gpio141", "gpio142",
+						"gpio107", "gpio110";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio22", "gpio141", "gpio142",
+						"gpio107", "gpio110";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
 		nx30p6093_intr_default: nx30p6093_intr_default {
 			mux {
 				pins = "gpio5";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
index 9a567a3..cf31c40 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -605,7 +605,7 @@
 		qcom,aux-cfg8-settings = [40 bb];
 		qcom,aux-cfg9-settings = [44 03];
 
-		qcom,max-pclk-frequency-khz = <675000>;
+		qcom,max-pclk-frequency-khz = <300000>;
 
 		qcom,ctrl-supply-entries {
 			#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index af44079..50ea44a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -376,6 +376,7 @@
 				2054400    876
 				2169600    900
 				2208000    924
+				2304000    940
 				2361600    948
 				2400000   1170
 				2457600   1200
@@ -418,6 +419,7 @@
 				2054400    87
 				2169600    90
 				2208000    92
+				2304000    93
 				2361600    94
 				2400000   117
 				2457600   120
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr-dvt.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr-dvt.dtsi
index 9409a4c..f710e40 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr-dvt.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr-dvt.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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
@@ -13,6 +13,48 @@
 #include "sdm845-camera-sensor-qvr.dtsi"
 /* PMD ToF MD101D */
 &cam_cci {
+	eeprom_depth2: qcom,eeprom@5 {
+		cell-index = <4>;
+		reg = <0x4>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_lvs1>;
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_eyetracking_force>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <0 3312000 1050000 0>;
+		rgltr-max-voltage = <0 3600000 1050000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk3_active
+				&cam_sensor_depth_active>;
+		pinctrl-1 = <&cam_sensor_mclk3_suspend
+				&cam_sensor_depth_suspend>;
+		gpios = <&tlmm 16 0>,
+			<&tlmm 28 0>,
+			<&tlmm 23 0>,
+			<&tlmm 24 0>;
+		gpio-reset = <1>;
+		gpio-vana = <2>;
+		gpio-vdig = <3>;
+		gpio-req-tbl-num = <0 1 2 3> ;
+		gpio-req-tbl-flags = <1 0 0 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1",
+					"CAM_VANA1",
+					"CAM_VDIG1";
+		sensor-position = <0>;
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK3_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
 	qcom,cam-sensor@4 {
 		cell-index = <4>;
 		compatible = "qcom,cam-sensor";
@@ -21,6 +63,7 @@
 		sensor-position-roll = <270>; /* checked, MTP845 */
 		sensor-position-pitch = <0>; /* checked, MTP845 */
 		sensor-position-yaw = <180>; /* checked, MTP845 */
+		eeprom-src = <&eeprom_depth2>;
 		cam_vio-supply = <&pm8998_lvs1>; /* checked, MTP845 */
 		cam_vana-supply = <&pmi8998_bob>;
 		cam_vdig-supply = <&camera_eyetracking_force>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi
index aa068e5..763e91a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -433,6 +433,47 @@
 		clock-rates = <24000000>;
 	};
 
+	eeprom_depth: qcom,eeprom@3 {
+		cell-index = <3>;
+		reg = <0x3>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_l9>;
+		cam_vana-supply = <&pm8998_l16>;
+		cam_vdig-supply = <&pm8998_l10>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1800000 3312000 1800000 0>;
+		rgltr-max-voltage = <1800000 3312000 1800000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+				&cam_sensor_iris_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+				&cam_sensor_iris_suspend>;
+		gpios = <&tlmm 15 0>,
+			<&tlmm 21 0>,
+			<&tlmm 122 0>,
+			<&tlmm 59 0>;
+		gpio-reset = <1>;
+		gpio-vana = <2>;
+		gpio-vdig = <3>;
+		gpio-req-tbl-num = <0 1 2 3> ;
+		gpio-req-tbl-flags = <1 0 0 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK3",
+					"CAM_RESET3",
+					"CAM_VANA3",
+					"CAM_VDIG3";
+		sensor-position = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
 	qcom,cam-sensor@3 {
 		cell-index = <3>;
 		compatible = "qcom,cam-sensor";
@@ -441,6 +482,7 @@
 		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
 		sensor-position-yaw = <0>;
+		eeprom-src = <&eeprom_depth>;
 		cam_vio-supply = <&pm8998_l9>;
 		cam_vana-supply = <&pm8998_l16>;
 		cam_vdig-supply = <&pm8998_l10>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
index c9669d9..eab5661 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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
@@ -147,6 +147,7 @@
 			"csiphy3_clk",
 			"csi3phytimer_clk_src",
 			"csi3phytimer_clk";
+		src-clock-name = "csi3phytimer_clk_src";
 		clock-cntl-level = "turbo";
 		clock-rates =
 			<0 0 0 0 384000000 0 269333333 0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
index 42299cd..9588aac 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017,2018 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
@@ -61,7 +61,7 @@
 		venus_bus_ddr {
 			compatible = "qcom,msm-vidc,bus";
 			label = "venus-ddr";
-			qcom,bus-master = <MSM_BUS_MASTER_VIDEO_P0>;
+			qcom,bus-master = <MSM_BUS_MASTER_LLCC>;
 			qcom,bus-slave = <MSM_BUS_SLAVE_EBI_CH0>;
 			qcom,bus-governor = "msm-vidc-ddr";
 			qcom,bus-range-kbps = <1000 3388000>;
@@ -80,7 +80,7 @@
 			qcom,bus-master = <MSM_BUS_MASTER_VIDEO_P0>;
 			qcom,bus-slave = <MSM_BUS_SLAVE_LLCC>;
 			qcom,bus-governor = "msm-vidc-llcc";
-			qcom,bus-range-kbps = <17000 125700>;
+			qcom,bus-range-kbps = <17000 3388000>;
 		};
 
 		/* MMUs */
diff --git a/arch/arm64/boot/dts/qcom/sdw2500-apq8009w-wtp.dts b/arch/arm64/boot/dts/qcom/sdw2500-apq8009w-wtp.dts
new file mode 100644
index 0000000..c5b8c75
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdw2500-apq8009w-wtp.dts
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909w-gpu.dtsi"
+#include "msm8909w.dtsi"
+#include "apq8009w-memory.dtsi"
+#include "8909w-pm660.dtsi"
+#include "spi-panel-st7789v2-qvga-cmd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 WTP SDW2500";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id =   <265 0>,
+			<301 0>;
+	qcom,board-id = <8 0x112>;
+	qcom,pmic-id =  <0x0001001b 0x0 0x0 0x0>,
+			<0x0001011b 0x0 0x0 0x0>;
+};
+
+&soc {
+	/delete-node/ qcom,msm-cpufreq;
+	qcom,msm-cpufreq {
+		reg = <0 4>;
+		compatible = "qcom,msm-cpufreq";
+		clocks = <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk", "cpu1_clk",
+				"cpu2_clk", "cpu3_clk";
+		qcom,cpufreq-table =
+			 <  400000 >,
+			 <  800000 >,
+			 < 1094400 >,
+			 < 1267200 >;
+	};
+
+	i2c@78b7000 { /* BLSP1 QUP3 */
+		synaptics@20 {
+			compatible = "synaptics,dsx-i2c";
+			reg = <0x20>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <98 0x2008>;
+			vdd_ana-supply = <&pm660_l18>;
+			vcc_i2c-supply = <&pm660_l13>;
+			synaptics,pwr-reg-name = "vdd_ana";
+			synaptics,bus-reg-name = "vcc_i2c";
+			pinctrl-names = "pmx_ts_active", "pmx_ts_suspend",
+							"pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			synaptics,irq-gpio = <&msm_gpio 98 0x2008>;
+			synaptics,irq-on-state = <0>;
+			synaptics,irq-flags = <0x2008>;
+			synaptics,power-delay-ms = <200>;
+			synaptics,max-y-for-2d = <389>;
+			synaptics,wakeup-gestures-en = <1>;
+			synaptics,resume-in-workqueue;
+			synaptics,x-flip;
+			synaptics,y-flip;
+
+			synaptics,reset-gpio = <&msm_gpio 31 0x0>;
+			synaptics,reset-delay-ms = <200>;
+			synaptics,reset-on-state = <0>;
+			synaptics,reset-active-ms = <20>;
+			/delete-property/ synaptics,display-coords;
+			/delete-property/ synaptics,panel-coords;
+			/delete-property/ synaptics,power-down;
+			/delete-property/ synaptics,disable-gpios;
+			/delete-property/ synaptics,is_wake;
+		};
+
+		/delete-node/ it7260@46;
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,mdss_spi_client {
+			reg = <0>;
+			compatible = "qcom,mdss-spi-client";
+			label = "MDSS SPI QUP4 CLIENT";
+			dc-gpio = <&msm_gpio 59 0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,msm-thermal {
+		vdd-dig-supply = <&pm660_s2_floor_corner>;
+
+		msm_thermal_freq: qcom,vdd-apps-rstr {
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <1094400>;
+			qcom,freq-req;
+		};
+	};
+
+	qcom,bcl {
+		compatible = "qcom,bcl";
+		qcom,bcl-enable;
+		qcom,bcl-framework-interface;
+		qcom,bcl-freq-control-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,bcl-hotplug-list = <&CPU2 &CPU3>;
+		qcom,bcl-soc-hotplug-list = <&CPU2 &CPU3>;
+		qcom,ibat-monitor {
+			qcom,low-threshold-uamp = <1000000>;
+			qcom,high-threshold-uamp = <2000000>;
+			qcom,mitigation-freq-khz = <1094400>;
+			qcom,vph-high-threshold-uv = <3500000>;
+			qcom,vph-low-threshold-uv = <3200000>;
+			qcom,soc-low-threshold = <10>;
+			qcom,thermal-handle = <&msm_thermal_freq>;
+		};
+	};
+
+	msm_digital_codec: msm-dig-codec@771c000 {
+		compatible = "qcom,msm-digital-codec";
+		reg = <0x0771c000 0x0>;
+
+		cdc-vdd-digital-supply = <&pm660_l11>;
+		qcom,cdc-vdd-digital-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-digital-current = <5000>;
+		qcom,cdc-on-demand-supplies = "cdc-vdd-digital";
+
+		qcom,subsys-name = "modem";
+	};
+
+	mdss_spi: qcom,mdss_spi {
+		compatible = "qcom,mdss-spi-display";
+		label = "mdss spi panel";
+
+		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
+		vdd-supply = <&pm660_l18>;
+		vddio-supply = <&pm660_l11>;
+
+		qcom,panel-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			qcom,panel-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdd";
+				qcom,supply-min-voltage = <3000000>;
+				qcom,supply-max-voltage = <3000000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+			qcom,panel-supply-entry@1 {
+				reg = <1>;
+				qcom,supply-name = "vddio";
+				qcom,supply-min-voltage = <1800000>;
+				qcom,supply-max-voltage = <3000000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+		};
+	};
+};
+
+&qcom_seecom {
+	reg = <0x87a00000 0x200000>;
+	reg-names = "secapp-region";
+	status = "okay";
+};
+
+&external_image_mem {
+	reg = <0x0 0x87a00000 0x0 0x0600000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x05600000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x8d600000 0x0 0x0600000>;
+};
+
+&i2c_1 {
+	status = "disabled";
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&i2c_4 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "okay";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&msm_gpio 50 0x00>;
+		qcom,nq-ven = <&msm_gpio 52 0x00>;
+		qcom,nq-firm = <&msm_gpio 38 0x00>;
+		qcom,nq-esepwr = <&msm_gpio 49 0x00>;
+		qcom,nq-clkreq = <&pm660_gpios 4 0x00>;
+		qcom,clk-src = "BBCLK3";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <50 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active","nfc_suspend";
+		pinctrl-0 = <&nfcw_int_active &nfcv2k_disable_active>;
+		pinctrl-1 = <&nfcw_int_suspend &nfcv2k_disable_suspend>;
+		clocks = <&clock_rpm clk_bb_clk3_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
+&i2c_5 {
+	status = "disabled";
+};
+
+&sdhc_2 {
+	status = "disabled";
+};
+
+&blsp1_uart1 {
+	status = "disabled";
+};
+
+&blsp1_uart2 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console2_sleep>;
+};
+
+/* Pinctrl dt nodes for interrupt & reset gpio for Synaptics touch controller */
+&ts_int_active {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_int_suspend {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_reset_active {
+	mux {
+		pins = "gpio31";
+	};
+
+	config {
+		pins = "gpio31";
+	};
+};
+
+&ts_reset_suspend {
+	mux {
+		pins = "gpio31";
+	};
+
+	config {
+		pins = "gpio31";
+	};
+};
+
+&ts_release {
+	mux {
+		pins = "gpio98", "gpio31";
+	};
+
+	config {
+		pins = "gpio98", "gpio31";
+	};
+};
+
+&vendor_fstab {
+	fsmgr_flags = "wait";
+};
+
+&mdss_dsi0{
+	qcom,dsi-pref-prim-pan = <&dsi_auo_390p_cmd>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
+};
+
+&spi_st7789v2_qvga_cmd {
+	qcom,panel-supply-entries = <&dsi_pm660_panel_pwr_supply>;
+	qcom,mdss-spi-bl-pmic-pwm-frequency = <100>;
+	qcom,mdss-spi-bl-pmic-bank-select = <0>;
+	qcom,cont-splash-enabled;
+};
+
+&mdss_spi {
+	qcom,spi-pref-prim-pan = <&spi_st7789v2_qvga_cmd>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_te_active>;
+	pinctrl-1 = <&mdss_te_suspend>;
+
+	qcom,platform-te-gpio = <&msm_gpio 24 0>;
+	qcom,platform-reset-gpio = <&msm_gpio 25 0>;
+	qcom,platform-spi-dc-gpio = <&msm_gpio 59 0>;
+
+	vdd-supply = <&pm660_l18>;
+	vddio-supply = <&pm660_l11>;
+};
+
+&dai_mi2s3 {
+	qcom,msm-mi2s-rx-lines = <1>;
+	qcom,msm-mi2s-tx-lines = <2>;
+};
+
+&audio_codec_mtp {
+	compatible = "qcom,msm8909-audio-codec";
+	qcom,model = "msm8909w-wtp-snd-card";
+	qcom,msm-ext-pa = "quaternary";
+	qcom,split-a2dp;
+	qcom,audio-routing =
+		"CDC_CONN", "MCLK",
+		"QUAT_MI2S_RX", "DIGIT_REGULATOR",
+		"TX_I2S_CLK", "DIGIT_REGULATOR",
+		"DMIC1", "Digital Mic1",
+		"DMIC2", "Digital Mic2";
+	qcom,msm-gpios =
+		"quat_i2s",
+		"dmic";
+	qcom,pinctrl-names =
+		"all_off",
+		"quat_i2s_act",
+		"dmic_act",
+		"quat_i2s_dmic_act";
+	pinctrl-names =
+		"all_off",
+		"quat_i2s_act",
+		"dmic_act",
+		"quat_i2s_dmic_act";
+	pinctrl-0 = <&quat_mi2s_sleep &quat_mi2s_din_sleep
+			&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+	pinctrl-1 = <&quat_mi2s_active &quat_mi2s_din_active
+			&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+	pinctrl-2 = <&quat_mi2s_sleep &quat_mi2s_din_sleep
+			&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+	pinctrl-3 = <&quat_mi2s_active &quat_mi2s_din_active
+			&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+	/delete-property/qcom,cdc-us-euro-gpios;
+
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdw2500-msm8909w-wtp.dts b/arch/arm64/boot/dts/qcom/sdw2500-msm8909w-wtp.dts
new file mode 100644
index 0000000..1ee14ac3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdw2500-msm8909w-wtp.dts
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909w-gpu.dtsi"
+#include "msm8909w.dtsi"
+#include "msm8909w-memory.dtsi"
+#include "8909w-pm660.dtsi"
+#include "spi-panel-st7789v2-qvga-cmd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 WTP SDW2500";
+	compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
+	qcom,msm-id =   <245 0>,
+			<258 0>,
+			<275 0>,
+			<300 0>;
+	qcom,board-id = <8 0x112>;
+	qcom,pmic-id =  <0x0001001b 0x0 0x0 0x0>,
+			<0x0001011b 0x0 0x0 0x0>;
+};
+
+&soc {
+	/delete-node/ qcom,msm-cpufreq;
+	qcom,msm-cpufreq {
+		reg = <0 4>;
+		compatible = "qcom,msm-cpufreq";
+		clocks = <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk", "cpu1_clk",
+				"cpu2_clk", "cpu3_clk";
+		qcom,cpufreq-table =
+			 <  400000 >,
+			 <  800000 >,
+			 < 1094400 >,
+			 < 1267200 >;
+	};
+
+	i2c@78b7000 { /* BLSP1 QUP3 */
+		synaptics@20 {
+			compatible = "synaptics,dsx-i2c";
+			reg = <0x20>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <98 0x2008>;
+			vdd_ana-supply = <&pm660_l18>;
+			vcc_i2c-supply = <&pm660_l13>;
+			synaptics,pwr-reg-name = "vdd_ana";
+			synaptics,bus-reg-name = "vcc_i2c";
+			pinctrl-names = "pmx_ts_active", "pmx_ts_suspend",
+							"pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			synaptics,irq-gpio = <&msm_gpio 98 0x2008>;
+			synaptics,irq-on-state = <0>;
+			synaptics,irq-flags = <0x2008>;
+			synaptics,power-delay-ms = <200>;
+			synaptics,max-y-for-2d = <389>;
+			synaptics,wakeup-gestures-en = <1>;
+			synaptics,resume-in-workqueue;
+			synaptics,x-flip;
+			synaptics,y-flip;
+
+			synaptics,reset-gpio = <&msm_gpio 31 0x0>;
+			synaptics,reset-delay-ms = <200>;
+			synaptics,reset-on-state = <0>;
+			synaptics,reset-active-ms = <20>;
+			/delete-property/ synaptics,display-coords;
+			/delete-property/ synaptics,panel-coords;
+			/delete-property/ synaptics,power-down;
+			/delete-property/ synaptics,disable-gpios;
+			/delete-property/ synaptics,is_wake;
+		};
+
+		/delete-node/ it7260@46;
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,mdss_spi_client {
+			reg = <0>;
+			compatible = "qcom,mdss-spi-client";
+			label = "MDSS SPI QUP4 CLIENT";
+			dc-gpio = <&msm_gpio 59 0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,msm-thermal {
+		vdd-dig-supply = <&pm660_s2_floor_corner>;
+
+		msm_thermal_freq: qcom,vdd-apps-rstr {
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <1094400>;
+			qcom,freq-req;
+		};
+	};
+
+	qcom,bcl {
+		compatible = "qcom,bcl";
+		qcom,bcl-enable;
+		qcom,bcl-framework-interface;
+		qcom,bcl-freq-control-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,bcl-hotplug-list = <&CPU2 &CPU3>;
+		qcom,bcl-soc-hotplug-list = <&CPU2 &CPU3>;
+		qcom,ibat-monitor {
+			qcom,low-threshold-uamp = <1000000>;
+			qcom,high-threshold-uamp = <2000000>;
+			qcom,mitigation-freq-khz = <1094400>;
+			qcom,vph-high-threshold-uv = <3500000>;
+			qcom,vph-low-threshold-uv = <3200000>;
+			qcom,soc-low-threshold = <10>;
+			qcom,thermal-handle = <&msm_thermal_freq>;
+		};
+	};
+
+	msm_digital_codec: msm-dig-codec@771c000 {
+		compatible = "qcom,msm-digital-codec";
+		reg = <0x0771c000 0x0>;
+		qcom,no-analog-codec;
+
+		cdc-vdd-digital-supply = <&pm660_l11>;
+		qcom,cdc-vdd-digital-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-digital-current = <10000>;
+		qcom,cdc-on-demand-supplies = "cdc-vdd-digital";
+
+		qcom,subsys-name = "modem";
+	};
+
+	mdss_spi: qcom,mdss_spi {
+		compatible = "qcom,mdss-spi-display";
+		label = "mdss spi panel";
+
+		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
+		vdd-supply = <&pm660_l18>;
+		vddio-supply = <&pm660_l11>;
+
+		qcom,panel-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			qcom,panel-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdd";
+				qcom,supply-min-voltage = <3000000>;
+				qcom,supply-max-voltage = <3000000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+			qcom,panel-supply-entry@1 {
+				reg = <1>;
+				qcom,supply-name = "vddio";
+				qcom,supply-min-voltage = <1800000>;
+				qcom,supply-max-voltage = <3000000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+		};
+	};
+
+	cdc_dmic_gpios: cdc_dmic_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+		pinctrl-1 = <&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+	};
+
+	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+	};
+};
+
+&qcom_seecom {
+	reg = <0x87a00000 0x200000>;
+	reg-names = "secapp-region";
+	status = "okay";
+};
+
+&external_image_mem {
+	reg = <0x0 0x87a00000 0x0 0x0600000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x05600000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x8d600000 0x0 0x0600000>;
+};
+
+&i2c_1 {
+	status = "disabled";
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&i2c_4 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "okay";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&msm_gpio 50 0x00>;
+		qcom,nq-ven = <&msm_gpio 52 0x00>;
+		qcom,nq-firm = <&msm_gpio 38 0x00>;
+		qcom,nq-esepwr = <&msm_gpio 49 0x00>;
+		qcom,nq-clkreq = <&pm660_gpios 4 0x00>;
+		qcom,clk-src = "BBCLK3";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <50 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active","nfc_suspend";
+		pinctrl-0 = <&nfcw_int_active &nfcv2k_disable_active>;
+		pinctrl-1 = <&nfcw_int_suspend &nfcv2k_disable_suspend>;
+		clocks = <&clock_rpm clk_bb_clk3_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
+&i2c_5 {
+	status = "disabled";
+};
+
+&sdhc_2 {
+	status = "disabled";
+};
+
+&blsp1_uart1 {
+	status = "disabled";
+};
+
+&blsp1_uart2 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console2_sleep>;
+};
+
+/* Pinctrl dt nodes for interrupt & reset gpio for Synaptics touch controller */
+&ts_int_active {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_int_suspend {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_reset_active {
+	mux {
+		pins = "gpio31";
+	};
+
+	config {
+		pins = "gpio31";
+	};
+};
+
+&ts_reset_suspend {
+	mux {
+		pins = "gpio31";
+	};
+
+	config {
+		pins = "gpio31";
+	};
+};
+
+&ts_release {
+	mux {
+		pins = "gpio98", "gpio31";
+	};
+
+	config {
+		pins = "gpio98", "gpio31";
+	};
+};
+
+&vendor_fstab {
+	fsmgr_flags = "wait";
+};
+
+&mdss_dsi0{
+	qcom,dsi-pref-prim-pan = <&dsi_auo_390p_cmd>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
+};
+
+&spi_st7789v2_qvga_cmd {
+	qcom,panel-supply-entries = <&dsi_pm660_panel_pwr_supply>;
+	qcom,mdss-spi-bl-pmic-pwm-frequency = <100>;
+	qcom,mdss-spi-bl-pmic-bank-select = <0>;
+	qcom,cont-splash-enabled;
+};
+
+&mdss_spi {
+	qcom,spi-pref-prim-pan = <&spi_st7789v2_qvga_cmd>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_te_active>;
+	pinctrl-1 = <&mdss_te_suspend>;
+
+	qcom,platform-te-gpio = <&msm_gpio 24 0>;
+	qcom,platform-reset-gpio = <&msm_gpio 25 0>;
+	qcom,platform-spi-dc-gpio = <&msm_gpio 59 0>;
+
+	vdd-supply = <&pm660_l18>;
+	vddio-supply = <&pm660_l11>;
+};
+
+&dai_mi2s3 {
+	qcom,msm-mi2s-rx-lines = <1>;
+	qcom,msm-mi2s-tx-lines = <2>;
+};
+
+&audio_codec_mtp {
+	compatible = "qcom,msm8909-audio-codec";
+	qcom,model = "msm8909w-wtp-snd-card";
+	qcom,msm-ext-pa = "quaternary";
+	qcom,split-a2dp;
+	qcom,audio-routing =
+		"CDC_CONN", "MCLK",
+		"QUAT_MI2S_RX", "DIGITAL_REGULATOR",
+		"TX_I2S_CLK", "DIGITAL_REGULATOR",
+		"DMIC1", "Digital Mic1",
+		"DMIC2", "Digital Mic2";
+	qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+	qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+	qcom,msm-gpios =
+		"quat_i2s",
+		"dmic";
+	qcom,pinctrl-names =
+		"all_off",
+		"quat_i2s_act",
+		"dmic_act",
+		"quat_i2s_dmic_act";
+	pinctrl-names =
+		"all_off",
+		"quat_i2s_act",
+		"dmic_act",
+		"quat_i2s_dmic_act";
+	pinctrl-0 = <&quat_mi2s_sleep &quat_mi2s_din_sleep
+			&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+	pinctrl-1 = <&quat_mi2s_active &quat_mi2s_din_active
+			&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+	pinctrl-2 = <&quat_mi2s_sleep &quat_mi2s_din_sleep
+			&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+	pinctrl-3 = <&quat_mi2s_active &quat_mi2s_din_active
+			&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+	/delete-property/qcom,cdc-us-euro-gpios;
+
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec";
+};
diff --git a/arch/arm64/boot/dts/qcom/spi-panel-st7789v2-qvga-cmd.dtsi b/arch/arm64/boot/dts/qcom/spi-panel-st7789v2-qvga-cmd.dtsi
new file mode 100644
index 0000000..a0d5c36
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/spi-panel-st7789v2-qvga-cmd.dtsi
@@ -0,0 +1,67 @@
+/* Copyright (c) 2018-2019, 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.
+ */
+
+&mdss_mdp {
+	spi_st7789v2_qvga_cmd: qcom,mdss_spi_st7789v2_qvga_cmd {
+		qcom,mdss-spi-panel-name =
+			"st7789v2 qvga command mode spi panel";
+		qcom,mdss-spi-panel-destination = "display_1";
+		qcom,mdss-spi-panel-controller = <&mdss_spi>;
+		qcom,mdss-spi-panel-framerate = <27>;
+		qcom,mdss-spi-panel-width = <240>;
+		qcom,mdss-spi-panel-height = <240>;
+		qcom,mdss-spi-h-front-porch = <79>;
+		qcom,mdss-spi-h-back-porch = <59>;
+		qcom,mdss-spi-h-pulse-width = <60>;
+		qcom,mdss-spi-v-back-porch = <10>;
+		qcom,mdss-spi-v-front-porch = <7>;
+		qcom,mdss-spi-v-pulse-width = <2>;
+		qcom,mdss-spi-h-left-border = <0>;
+		qcom,mdss-spi-h-right-border = <0>;
+		qcom,mdss-spi-v-top-border = <0>;
+		qcom,mdss-spi-v-bottom-border = <0>;
+		qcom,mdss-spi-bpp = <16>;
+		qcom,mdss-spi-on-command = [
+				96 01 11
+				00 02 36 00
+				00 02 3A 05
+				00 02 35 00
+				00 06 B2 0C 0C 00 33 33
+				00 02 B7 75
+				00 02 BB 3D
+				00 02 C2 01
+				00 02 C3 19
+				00 02 04 20
+				00 02 C6 0F
+				00 03 D0 A4 A1
+				00 0F E0 70 04 08 09 09 05 2A 33
+					41 07 13 13 29 2F
+				00 0F E1 70 03 09 0A 09 06 2B 34
+					41 07 12 14 28 2E
+				00 01 21
+				00 01 29
+				00 05 2A 00 00 00 EF
+				00 05 2B 00 00 00 EF
+				00 01 2C];
+		qcom,mdss-spi-off-command = [20 01 28
+				20 01 10];
+		qcom,mdss-spi-bl-min-level = <1>;
+		qcom,mdss-spi-bl-max-level = <255>;
+		qcom,mdss-spi-bl-pmic-control-type = "bl_gpio_pulse";
+		qcom,mdss-spi-reset-sequence = <1 20>, <0 1>, <1 20>;
+		qcom,mdss-spi-panel-status-check-mode = "reg_read";
+		qcom,mdss-spi-panel-status-reg = /bits/ 8 <0x0a>;
+		qcom,mdss-spi-panel-status-read-length = <1>;
+		qcom,mdss-spi-panel-max-error-count = <1>;
+		qcom,mdss-spi-panel-status-value = /bits/ 8 <0x9c>;
+	};
+};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index c71f860..ac4b8c9 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -639,7 +639,6 @@
 CONFIG_CORESIGHT_STM=y
 CONFIG_CORESIGHT_TPDA=y
 CONFIG_CORESIGHT_TPDM=y
-CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
 CONFIG_PFK=y
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index e0b731e..c845bf5 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -779,8 +779,8 @@
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		/* Ignore if we don't have an event or if it's a zombie event */
-		if (!event || event->state == PERF_EVENT_STATE_ZOMBIE)
+		/* Ignore if we don't have an event */
+		if (!event || event->state != PERF_EVENT_STATE_ACTIVE)
 			continue;
 
 		/*
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 42dde2d..5553c01 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -1288,9 +1288,14 @@
 	while (count) {
 		int j, order = __fls(count);
 
-		pages[i] = alloc_pages(gfp, order);
-		while (!pages[i] && order)
-			pages[i] = alloc_pages(gfp, --order);
+		pages[i] = alloc_pages(order ? (gfp | __GFP_NORETRY) &
+					~__GFP_RECLAIM : gfp, order);
+		while (!pages[i] && order) {
+			order--;
+			pages[i] = alloc_pages(order ? (gfp | __GFP_NORETRY) &
+					~__GFP_RECLAIM : gfp, order);
+		}
+
 		if (!pages[i])
 			goto error;
 
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 9afd9a9..6631e20 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -52,3 +52,11 @@
 	  Say 'y' here to allow the regmap debugfs write. Regmap debugfs write
 	  could be risky when accessing some essential hardwares, so it is not
 	  recommended to enable this option on any production device.
+
+config REGMAP_SND_DIGCDC
+    depends on SND_SOC
+    bool "For regmap on DIGCDC"
+    select REGMAP_MMIO
+    default n
+    help
+      Say 'y' here to enable regmap_mmio for digital codec.
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index 86cc533..7282197 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -3,6 +3,5 @@
 obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_hsic.o
 obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_smux.o
 obj-$(CONFIG_MSM_MHI) += diagfwd_mhi.o
-obj-$(CONFIG_DIAG_OVER_PCIE) += diag_pcie.o
 obj-$(CONFIG_DIAG_USES_SMD) += diagfwd_smd.o
-diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagfwd_glink.o diagfwd_peripheral.o diagfwd_socket.o diag_mux.o diag_memorydevice.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
+diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagfwd_glink.o diagfwd_peripheral.o diagfwd_socket.o diag_mux.o diag_memorydevice.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o diag_pcie.o
\ No newline at end of file
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 0937b2f..5a1afd0 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -2757,10 +2757,11 @@
 
 int diag_dci_init(void)
 {
-	int ret = 0;
+	int ret = 0, i;
 
 	driver->dci_tag = 0;
-	driver->dci_client_id = 0;
+	for (i = 0; i < MAX_DCI_CLIENTS; i++)
+		driver->dci_client_id[i] = 0;
 	driver->num_dci_client = 0;
 	mutex_init(&driver->dci_mutex);
 	mutex_init(&dci_log_mask_mutex);
@@ -2956,8 +2957,8 @@
 	mutex_init(&new_entry->write_buf_mutex);
 	new_entry->dci_log_mask =  vzalloc(DCI_LOG_MASK_SIZE);
 	if (!new_entry->dci_log_mask) {
-		pr_err("diag: Unable to create log mask for client, %d",
-							driver->dci_client_id);
+		pr_err("diag: Unable to create log mask for DCI client, tgid: %d\n",
+			current->tgid);
 		goto fail_alloc;
 	}
 	create_dci_log_mask_tbl(new_entry->dci_log_mask, DCI_LOG_MASK_CLEAN);
@@ -3006,17 +3007,24 @@
 		proc_buf->buf_curr = proc_buf->buf_primary;
 	}
 
-	list_add_tail(&new_entry->track, &driver->dci_client_list);
-	driver->dci_client_id++;
-	new_entry->client_info.client_id = driver->dci_client_id;
-	reg_entry->client_id = driver->dci_client_id;
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		if (driver->dci_client_id[i] == 0)
+			break;
+	}
+
+	if (i == MAX_DCI_CLIENTS)
+		goto fail_alloc;
+	driver->dci_client_id[i] = 1;
+	new_entry->client_info.client_id = i+1;
+	reg_entry->client_id = i+1;
 	driver->num_dci_client++;
+	list_add_tail(&new_entry->track, &driver->dci_client_list);
 	if (driver->num_dci_client == 1)
 		diag_update_proc_vote(DIAG_PROC_DCI, VOTE_UP, reg_entry->token);
 	queue_work(driver->diag_real_time_wq, &driver->diag_real_time_work);
 	mutex_unlock(&driver->dci_mutex);
 
-	return driver->dci_client_id;
+	return reg_entry->client_id;
 
 fail_alloc:
 	if (new_entry) {
@@ -3075,7 +3083,11 @@
 	 */
 	if (!list_empty(&entry->track))
 		list_del(&entry->track);
+
+	if (entry->client_info.client_id > MAX_DCI_CLIENTS)
+		return DIAG_DCI_NO_REG;
 	driver->num_dci_client--;
+	driver->dci_client_id[entry->client_info.client_id - 1] = 0;
 	/*
 	 * Clear the client's log and event masks, update the cumulative
 	 * masks and send the masks to peripherals
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2fb0e3f..835c0c1 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018-2019 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
@@ -12,7 +12,6 @@
 #ifndef DIAG_DCI_H
 #define DIAG_DCI_H
 
-#define MAX_DCI_CLIENTS		10
 #define DCI_PKT_RSP_CODE	0x93
 #define DCI_DELAYED_RSP_CODE	0x94
 #define DCI_CONTROL_PKT_CODE	0x9A
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 6e0dba5..19b2b02 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2019, 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
@@ -44,9 +44,7 @@
 static int diag_dbgfs_table_index;
 static int diag_dbgfs_mempool_index;
 static int diag_dbgfs_usbinfo_index;
-#ifdef CONFIG_DIAG_OVER_PCIE
 static int diag_dbgfs_pcieinfo_index;
-#endif
 static int diag_dbgfs_smdinfo_index;
 static int diag_dbgfs_socketinfo_index;
 static int diag_dbgfs_glinkinfo_index;
@@ -485,7 +483,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_DIAG_OVER_PCIE
 static ssize_t diag_dbgfs_read_pcieinfo(struct file *file, char __user *ubuf,
 				       size_t count, loff_t *ppos)
 {
@@ -545,7 +542,6 @@
 	kfree(buf);
 	return ret;
 }
-#endif
 
 #ifdef CONFIG_DIAG_USES_SMD
 static ssize_t diag_dbgfs_read_smdinfo(struct file *file, char __user *ubuf,
@@ -1146,11 +1142,9 @@
 	.read = diag_dbgfs_read_usbinfo,
 };
 
-#ifdef CONFIG_DIAG_OVER_PCIE
 const struct file_operations diag_dbgfs_pcieinfo_ops = {
 	.read = diag_dbgfs_read_pcieinfo,
 };
-#endif
 
 const struct file_operations diag_dbgfs_dcistats_ops = {
 	.read = diag_dbgfs_read_dcistats,
@@ -1211,12 +1205,10 @@
 	if (!entry)
 		goto err;
 
-#ifdef CONFIG_DIAG_OVER_PCIE
 	entry = debugfs_create_file("pcieinfo", 0444, diag_dbgfs_dent, 0,
 				    &diag_dbgfs_pcieinfo_ops);
 	if (!entry)
 		goto err;
-#endif
 
 	entry = debugfs_create_file("dci_stats", 0444, diag_dbgfs_dent, 0,
 				    &diag_dbgfs_dcistats_ops);
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 7be5a06..3952094 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1772,6 +1772,7 @@
 		mask_info->update_buf = kzalloc(update_buf_len, GFP_KERNEL);
 		if (!mask_info->update_buf) {
 			kfree(mask_info->ptr);
+			mask_info->ptr = NULL;
 			return -ENOMEM;
 		}
 		kmemleak_not_leak(mask_info->update_buf);
diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c
index ae59175..e742d08 100644
--- a/drivers/char/diag/diag_mux.c
+++ b/drivers/char/diag/diag_mux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, 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
@@ -31,12 +31,6 @@
 #include "diagfwd_peripheral.h"
 #include "diag_ipc_logging.h"
 
-#ifdef CONFIG_DIAG_OVER_PCIE
-#define diag_mux_register_ops diag_pcie_register_ops
-#else
-#define diag_mux_register_ops diag_usb_register_ops
-#endif
-
 struct diag_mux_state_t *diag_mux;
 static struct diag_logger_t usb_logger;
 static struct diag_logger_t md_logger;
@@ -58,7 +52,6 @@
 	.close_peripheral = diag_md_close_peripheral,
 };
 
-#ifdef CONFIG_DIAG_OVER_PCIE
 static struct diag_logger_ops pcie_log_ops = {
 	.open = diag_pcie_connect_all,
 	.close = diag_pcie_disconnect_all,
@@ -66,7 +59,6 @@
 	.write = diag_pcie_write,
 	.close_peripheral = NULL
 };
-#endif
 
 int diag_mux_init(void)
 {
@@ -82,18 +74,16 @@
 	md_logger.mode = DIAG_MEMORY_DEVICE_MODE;
 	md_logger.log_ops = &md_log_ops;
 	diag_md_init();
-#ifdef CONFIG_DIAG_OVER_PCIE
 	pcie_logger.mode = DIAG_PCIE_MODE;
 	pcie_logger.log_ops = &pcie_log_ops;
 	diag_mux->pcie_ptr = &pcie_logger;
-#endif
 	/*
 	 * Set USB logging as the default logger. This is the mode
 	 * Diag should be in when it initializes.
 	 */
 	diag_mux->usb_ptr = &usb_logger;
 	diag_mux->md_ptr = &md_logger;
-	switch (driver->transport_set) {
+	switch (driver->pcie_transport_def) {
 	case DIAG_ROUTE_TO_PCIE:
 		diag_mux->logger = &pcie_logger;
 		diag_mux->mode = DIAG_PCIE_MODE;
@@ -113,7 +103,6 @@
 	kfree(diag_mux);
 }
 
-#ifdef CONFIG_DIAG_OVER_PCIE
 int diag_pcie_register_ops(int proc, int ctx, struct diag_mux_ops *ops)
 {
 	int err = 0;
@@ -127,22 +116,13 @@
 	pcie_logger.ops[proc] = ops;
 	err = diag_pcie_register(proc, ctx, ops);
 	if (err) {
-		driver->transport_set = DIAG_ROUTE_TO_USB;
-		diag_mux->logger = &usb_logger;
-		diag_mux->mode = DIAG_USB_MODE;
-		usb_logger.ops[proc] = ops;
-		err = diag_usb_register(proc, ctx, ops);
-		if (err) {
-			pr_err("diag: MUX: unable to register usb operations for proc: %d, err: %d\n",
-					   proc, err);
-			return err;
-		}
 		pr_err("diag: MUX: unable to register pcie operations for proc: %d, err: %d\n",
 			proc, err);
+		return err;
 	}
 	return 0;
 }
-#else
+
 int diag_usb_register_ops(int proc, int ctx, struct diag_mux_ops *ops)
 {
 	int err = 0;
@@ -161,7 +141,6 @@
 	}
 	return 0;
 }
-#endif
 
 int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
 {
@@ -172,9 +151,17 @@
 
 	if (proc < 0 || proc >= NUM_MUX_PROC)
 		return 0;
-	err = diag_mux_register_ops(proc, ctx, ops);
-	if (err)
+	err = diag_pcie_register_ops(proc, ctx, ops);
+	if (err) {
+		pr_err("diag: MUX: unable to register PCIe operations, continuing with USB registrations for proc: %d, err: %d\n",
+		proc, err);
+	}
+	err = diag_usb_register_ops(proc, ctx, ops);
+	if (err) {
+		pr_err("diag: MUX: unable to register USB operations for proc: %d, err: %d\n",
+		proc, err);
 		return err;
+	}
 	md_logger.ops[proc] = ops;
 	err = diag_md_register(proc, ctx, ops);
 	if (err) {
@@ -182,7 +169,6 @@
 		       proc, err);
 		return err;
 	}
-
 	return 0;
 }
 
@@ -308,6 +294,10 @@
 			diag_mux->pcie_ptr->log_ops->close();
 			diag_mux->logger = diag_mux->md_ptr;
 			diag_mux->md_ptr->log_ops->open();
+		} else if (*req_mode == DIAG_USB_MODE) {
+			diag_mux->pcie_ptr->log_ops->close();
+			diag_mux->logger = diag_mux->usb_ptr;
+			diag_mux->usb_ptr->log_ops->open();
 		} else if (*req_mode == DIAG_MULTI_MODE) {
 			diag_mux->md_ptr->log_ops->open();
 			diag_mux->logger = NULL;
@@ -318,6 +308,10 @@
 			diag_mux->usb_ptr->log_ops->close();
 			diag_mux->logger = diag_mux->md_ptr;
 			diag_mux->md_ptr->log_ops->open();
+		} else if (*req_mode == DIAG_PCIE_MODE) {
+			diag_mux->usb_ptr->log_ops->close();
+			diag_mux->logger = diag_mux->pcie_ptr;
+			diag_mux->pcie_ptr->log_ops->open();
 		} else if (*req_mode == DIAG_MULTI_MODE) {
 			diag_mux->md_ptr->log_ops->open();
 			diag_mux->logger = NULL;
@@ -333,7 +327,8 @@
 			diag_mux->logger = diag_mux->pcie_ptr;
 			diag_mux->pcie_ptr->log_ops->open();
 		} else if (*req_mode == DIAG_MULTI_MODE) {
-			if (driver->transport_set == DIAG_ROUTE_TO_PCIE)
+			if (driver->pcie_transport_def == DIAG_ROUTE_TO_PCIE ||
+				driver->transport_set == DIAG_ROUTE_TO_PCIE)
 				diag_mux->pcie_ptr->log_ops->open();
 			else
 				diag_mux->usb_ptr->log_ops->open();
diff --git a/drivers/char/diag/diag_mux.h b/drivers/char/diag/diag_mux.h
index dac08b3..c822f71 100644
--- a/drivers/char/diag/diag_mux.h
+++ b/drivers/char/diag/diag_mux.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019, 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
@@ -77,5 +77,4 @@
 int diag_mux_switch_logging(int *new_mode, int *peripheral_mask);
 int diag_pcie_register_ops(int proc, int ctx, struct diag_mux_ops *ops);
 int diag_usb_register_ops(int proc, int ctx, struct diag_mux_ops *ops);
-int diag_mux_register_ops(int proc, int ctx, struct diag_mux_ops *ops);
 #endif
diff --git a/drivers/char/diag/diag_pcie.c b/drivers/char/diag/diag_pcie.c
index 8f53573..bf048c1 100644
--- a/drivers/char/diag/diag_pcie.c
+++ b/drivers/char/diag/diag_pcie.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -85,6 +85,7 @@
 	ureq.mode = IPA_DMA_SYNC;
 	ureq.buf = pcie_info->in_chan_attr.read_buffer;
 	ureq.len = pcie_info->in_chan_attr.read_buffer_size;
+	ureq.transfer_len = 0;
 	bytes_avail = mhi_dev_read_channel(&ureq);
 	if (bytes_avail < 0)
 		return;
@@ -319,7 +320,7 @@
 	pcie_info = &diag_pcie[id];
 
 	if (len > pcie_info->out_chan_attr.max_pkt_size) {
-		DIAG_LOG(DIAG_DEBUG_MUX, "len: %d, max_size: %d\n",
+		DIAG_LOG(DIAG_DEBUG_MUX, "len: %d, max_size: %zu\n",
 			 len, pcie_info->out_chan_attr.max_pkt_size);
 		return diag_pcie_write_ext(pcie_info, buf, len, ctxt);
 	}
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index f960e8b..3a1c92e 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019 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
@@ -325,8 +325,8 @@
 		DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n",
 			 atomic_read(&entry->ref_count));
 		diag_ws_on_copy_complete(DIAG_WS_MUX);
-		spin_unlock_irqrestore(&ch->write_lock, flags);
 		diagmem_free(driver, req, ch->mempool);
+		spin_unlock_irqrestore(&ch->write_lock, flags);
 		return;
 	}
 	DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n",
@@ -344,8 +344,8 @@
 	buf = NULL;
 	len = 0;
 	ctxt = 0;
-	spin_unlock_irqrestore(&ch->write_lock, flags);
 	diagmem_free(driver, req, ch->mempool);
+	spin_unlock_irqrestore(&ch->write_lock, flags);
 }
 
 static void diag_usb_notifier(void *priv, unsigned int event,
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 2e87d51..264443d 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -288,6 +288,7 @@
 #define DIAG_CNTL_TYPE		2
 #define DIAG_DCI_TYPE		3
 
+#define MAX_DCI_CLIENTS		10
 /*
  * List of diag ids
  * 0 is reserved for unknown diag id, 1 for apps, diag ids
@@ -582,7 +583,7 @@
 	struct list_head dci_req_list;
 	struct list_head dci_client_list;
 	int dci_tag;
-	int dci_client_id;
+	int dci_client_id[MAX_DCI_CLIENTS];
 	struct mutex dci_mutex;
 	int num_dci_client;
 	unsigned char *apps_dci_buf;
@@ -595,11 +596,13 @@
 	uint32_t cmd_reg_count;
 	struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS];
 	int transport_set;
+	int pcie_transport_def;
 	/* Sizes that reflect memory pool sizes */
 	unsigned int poolsize;
 	unsigned int poolsize_hdlc;
 	unsigned int poolsize_dci;
 	unsigned int poolsize_user;
+	spinlock_t diagmem_lock;
 	/* Buffers for masks */
 	struct mutex diag_cntl_mutex;
 	/* Members for Sending response */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index cb04195..ad1a12c 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -204,6 +204,7 @@
 	if ((count < ret+length) || (copy_to_user(buf,		\
 			(void *)&data, length))) {		\
 		ret = -EFAULT;					\
+		break;							\
 	}							\
 	ret += length;						\
 } while (0)
@@ -216,17 +217,19 @@
 static void diag_drain_apps_data(struct diag_apps_data_t *data)
 {
 	int err = 0;
+	unsigned long flags;
 
 	if (!data || !data->buf)
 		return;
 
 	err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len,
 			     data->ctxt);
+	spin_lock_irqsave(&driver->diagmem_lock, flags);
 	if (err)
 		diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
-
 	data->buf = NULL;
 	data->len = 0;
+	spin_unlock_irqrestore(&driver->diagmem_lock, flags);
 }
 
 void diag_update_user_client_work_fn(struct work_struct *work)
@@ -297,6 +300,8 @@
 	diagmem_init(driver, POOL_TYPE_HDLC);
 	diagmem_init(driver, POOL_TYPE_USER);
 	diagmem_init(driver, POOL_TYPE_DCI);
+
+	spin_lock_init(&driver->diagmem_lock);
 }
 
 static void diag_mempool_exit(void)
@@ -454,8 +459,19 @@
 	session_info = diag_md_session_get_pid(pid);
 	if (!session_info) {
 		mutex_unlock(&driver->md_session_lock);
+		if (driver->pcie_transport_def == DIAG_ROUTE_TO_PCIE)
+			params.req_mode = PCIE_MODE;
+		else
+			params.req_mode = USB_MODE;
+		params.mode_param = 0;
+		params.pd_mask = 0;
+		params.peripheral_mask = DIAG_CON_ALL;
+		mutex_lock(&driver->diagchar_mutex);
+		diag_switch_logging(&params);
+		mutex_unlock(&driver->diagchar_mutex);
 		return;
 	}
+
 	session_mask = session_info->peripheral_mask;
 	mutex_unlock(&driver->md_session_lock);
 
@@ -469,10 +485,12 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++)
 		if (MD_PERIPHERAL_MASK(i) & session_mask)
 			diag_mux_close_peripheral(DIAG_LOCAL_PROC, i);
+
 	if (driver->transport_set == DIAG_ROUTE_TO_PCIE)
 		params.req_mode = PCIE_MODE;
 	else
 		params.req_mode = USB_MODE;
+
 	params.mode_param = 0;
 	params.pd_mask = 0;
 	params.peripheral_mask = p_mask;
@@ -1554,10 +1572,15 @@
 		req_mode != DIAG_PCIE_MODE)
 		return -EINVAL;
 
-	if (req_mode == DIAG_USB_MODE || req_mode == DIAG_PCIE_MODE) {
-		if (curr_mode == req_mode)
-			return 0;
+	if (curr_mode == req_mode)
+		return 0;
 
+	if ((req_mode ==  DIAG_USB_MODE && curr_mode == DIAG_PCIE_MODE) ||
+		(req_mode == DIAG_PCIE_MODE && curr_mode == DIAG_USB_MODE)) {
+		*change_mode = 1;
+		return 0;
+	} else if ((req_mode == DIAG_USB_MODE || req_mode == DIAG_PCIE_MODE)
+		&& curr_mode == DIAG_MEMORY_DEVICE_MODE) {
 		mutex_lock(&driver->md_session_lock);
 		if (driver->md_session_mode == DIAG_MD_NONE
 		    && driver->md_session_mask == 0 && driver->logging_mask) {
@@ -1607,7 +1630,7 @@
 		/* If all peripherals are being set to USB Mode, call close */
 		if (~change_mask & peripheral_mask) {
 			err = diag_md_peripheral_switch(current->tgid,
-					change_mask, DIAG_USB_MODE);
+					change_mask, req_mode);
 		} else
 			diag_md_session_close(current->tgid);
 		mutex_unlock(&driver->md_session_lock);
@@ -1631,7 +1654,7 @@
 				mutex_unlock(&driver->md_session_lock);
 				return -EINVAL;
 			}
-			if (driver->transport_set == DIAG_ROUTE_TO_PCIE)
+			if (driver->pcie_transport_def == DIAG_ROUTE_TO_PCIE)
 				err = diag_md_peripheral_switch(current->tgid,
 					change_mask, DIAG_PCIE_MODE);
 			else
@@ -1865,6 +1888,15 @@
 	}
 	driver->logging_mode = new_mode;
 	driver->logging_mask = peripheral_mask;
+	if (new_mode == DIAG_PCIE_MODE) {
+		driver->transport_set = DIAG_ROUTE_TO_PCIE;
+		diagmem_setsize(POOL_TYPE_MUX_APPS, itemsize_pcie_apps,
+			poolsize_pcie_apps + 1 + (NUM_PERIPHERALS * 6));
+	} else if (new_mode == DIAG_USB_MODE) {
+		driver->transport_set = DIAG_ROUTE_TO_USB;
+		diagmem_setsize(POOL_TYPE_MUX_APPS, itemsize_usb_apps,
+			poolsize_usb_apps + 1 + (NUM_PERIPHERALS * 6));
+	}
 	DIAG_LOG(DIAG_DEBUG_USERSPACE,
 		"Switch logging to %d mask:%0x\n", new_mode, peripheral_mask);
 
@@ -2764,6 +2796,7 @@
 	struct diag_apps_data_t *data = &hdlc_data;
 	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+	unsigned long flags;
 	/*
 	 * The maximum encoded size of the buffer can be atmost twice the length
 	 * of the packet. Add three bytes foe footer - 16 bit CRC (2 bytes) +
@@ -2868,10 +2901,11 @@
 	return PKT_ALLOC;
 
 fail_free_buf:
+	spin_lock_irqsave(&driver->diagmem_lock, flags);
 	diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
 	data->buf = NULL;
 	data->len = 0;
-
+	spin_unlock_irqrestore(&driver->diagmem_lock, flags);
 fail_ret:
 	return ret;
 }
@@ -2883,6 +2917,7 @@
 	int ret = PKT_DROP;
 	struct diag_pkt_frame_t header;
 	struct diag_apps_data_t *data = &non_hdlc_data;
+	unsigned long flags;
 	/*
 	 * The maximum packet size, when the data is non hdlc encoded is equal
 	 * to the size of the packet frame header and the length. Add 1 for the
@@ -2947,10 +2982,11 @@
 	return PKT_ALLOC;
 
 fail_free_buf:
+	spin_lock_irqsave(&driver->diagmem_lock, flags);
 	diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
 	data->buf = NULL;
 	data->len = 0;
-
+	spin_unlock_irqrestore(&driver->diagmem_lock, flags);
 fail_ret:
 	return ret;
 }
@@ -3952,6 +3988,39 @@
 	return 0;
 }
 
+#ifdef CONFIG_DIAG_OVER_PCIE
+static void diag_init_transport(void)
+{
+	driver->transport_set = DIAG_ROUTE_TO_PCIE;
+	driver->pcie_transport_def = DIAG_ROUTE_TO_PCIE;
+	driver->logging_mode = DIAG_PCIE_MODE;
+	/*
+	 * POOL_TYPE_MUX_APPS is for the buffers in the Diag MUX layer.
+	 * The number of buffers encompasses Diag data generated on
+	 * the Apss processor + 1 for the responses generated
+	 * exclusively on the Apps processor + data from data channels
+	 *(4 channels periperipheral) + data from command channels (2)
+	 */
+	diagmem_setsize(POOL_TYPE_MUX_APPS, itemsize_pcie_apps,
+		poolsize_pcie_apps + 1 + (NUM_PERIPHERALS * 6));
+}
+#else
+static void diag_init_transport(void)
+{
+	driver->transport_set = DIAG_ROUTE_TO_USB;
+	driver->pcie_transport_def = DIAG_ROUTE_TO_USB;
+	driver->logging_mode = DIAG_USB_MODE;
+	/*
+	 * POOL_TYPE_MUX_APPS is for the buffers in the Diag MUX layer.
+	 * The number of buffers encompasses Diag data generated on
+	 * the Apss processor + 1 for the responses generated
+	 * exclusively on the Apps processor + data from data channels
+	 *(4 channels periperipheral) + data from command channels (2)
+	 */
+	diagmem_setsize(POOL_TYPE_MUX_APPS, itemsize_usb_apps,
+		poolsize_usb_apps + 1 + (NUM_PERIPHERALS * 6));
+}
+#endif
 static int __init diagchar_init(void)
 {
 	dev_t dev;
@@ -3965,11 +4034,7 @@
 	kmemleak_not_leak(driver);
 
 	timer_in_progress = 0;
-#ifdef CONFIG_DIAG_OVER_PCIE
-	driver->transport_set = DIAG_ROUTE_TO_PCIE;
-#else
-	driver->transport_set = DIAG_ROUTE_TO_USB;
-#endif
+	diag_init_transport();
 	DIAG_LOG(DIAG_DEBUG_MUX, "Transport type set to %d\n",
 		driver->transport_set);
 	driver->delayed_rsp_id = 0;
@@ -3984,22 +4049,6 @@
 	driver->poolsize_dci = poolsize_dci;
 	driver->poolsize_user = poolsize_user;
 	driver->num_clients = max_clients;
-	if (driver->transport_set == DIAG_ROUTE_TO_PCIE) {
-		driver->logging_mode = DIAG_PCIE_MODE;
-		/*
-		 * POOL_TYPE_MUX_APPS is for the buffers in the Diag MUX layer.
-		 * The number of buffers encompasses Diag data generated on
-		 * the Apss processor + 1 for the responses generated
-		 * exclusively on the Apps processor + data from data channels
-		 *(4 channels periperipheral) + data from command channels (2)
-		 */
-		diagmem_setsize(POOL_TYPE_MUX_APPS, itemsize_pcie_apps,
-			poolsize_pcie_apps + 1 + (NUM_PERIPHERALS * 6));
-	} else {
-		driver->logging_mode = DIAG_USB_MODE;
-		diagmem_setsize(POOL_TYPE_MUX_APPS, itemsize_usb_apps,
-			poolsize_usb_apps + 1 + (NUM_PERIPHERALS * 6));
-	}
 
 	for (i = 0; i < NUM_UPD; i++) {
 		driver->pd_logging_mode[i] = 0;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 60a98b6..da39b1d 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -1829,9 +1829,11 @@
 			diagfwd_write_done(peripheral, type, num);
 			diag_ws_on_copy(DIAG_WS_MUX);
 		} else if (peripheral == APPS_DATA) {
+			spin_lock_irqsave(&driver->diagmem_lock, flags);
 			diagmem_free(driver, (unsigned char *)buf,
 				     POOL_TYPE_HDLC);
 			buf = NULL;
+			spin_unlock_irqrestore(&driver->diagmem_lock, flags);
 		} else {
 			pr_err_ratelimited("diag: Invalid peripheral %d in %s, type: %d\n",
 					   peripheral, __func__, type);
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index ada645d..2a36025 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2014, 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 2016, 2019 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
@@ -221,7 +221,7 @@
 			break;
 		}
 		spin_lock_irqsave(&mempool->lock, flags);
-		if (mempool->count > 0) {
+		if (mempool->count > 0 && buf) {
 			mempool_free(buf, mempool->pool);
 			atomic_add(-1, (atomic_t *)&mempool->count);
 		} else {
diff --git a/drivers/clk/msm/clock-gcc-8952.c b/drivers/clk/msm/clock-gcc-8952.c
index 06f095c..ed39a8ba 100644
--- a/drivers/clk/msm/clock-gcc-8952.c
+++ b/drivers/clk/msm/clock-gcc-8952.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, 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
@@ -371,6 +371,7 @@
 DEFINE_EXT_CLK(gpll0_ao_clk_src, NULL);
 DEFINE_EXT_CLK(gpll0_out_aux_clk_src, &gpll0_clk_src.c);
 DEFINE_EXT_CLK(gpll0_out_main_clk_src, &gpll0_clk_src.c);
+DEFINE_EXT_CLK(gpll0_gfx_clk_src, &gpll0_clk_src.c);
 DEFINE_EXT_CLK(ext_pclk0_clk_src, NULL);
 DEFINE_EXT_CLK(ext_byte0_clk_src, NULL);
 DEFINE_EXT_CLK(ext_pclk1_clk_src, NULL);
@@ -428,6 +429,7 @@
 
 DEFINE_EXT_CLK(gpll6_aux_clk_src, &gpll6_clk_src.c);
 DEFINE_EXT_CLK(gpll6_out_main_clk_src, &gpll6_clk_src.c);
+DEFINE_EXT_CLK(gpll6_gfx_clk_src, &gpll6_clk_src.c);
 
 static struct alpha_pll_masks pll_masks_p = {
 	.lock_mask = BIT(31),
@@ -843,6 +845,7 @@
 	F_SLEW( 400000000, FIXED_CLK_SRC, gpll0,	2,	0,	0),
 	F_SLEW( 465000000, 930000000,	  gpll3,	1,	0,	0),
 	F_SLEW( 484800000, 969600000,	  gpll3,	1,	0,	0),
+	F_SLEW( 500000000, 1000000000,	  gpll3,	1,	0,	0),
 	F_SLEW( 523200000, 1046400000,	  gpll3,	1,	0,	0),
 	F_SLEW( 550000000, 1100000000,	  gpll3,	1,	0,	0),
 	F_SLEW( 598000000, 1196000000,	  gpll3,	1,	0,	0),
@@ -864,6 +867,7 @@
 	F_SLEW( 400000000, FIXED_CLK_SRC, gpll0,	2,	0,	0),
 	F_SLEW( 465000000, 930000000,	  gpll3,	1,	0,	0),
 	F_SLEW( 484800000, 969600000,	  gpll3,	1,	0,	0),
+	F_SLEW( 500000000, 1000000000,	  gpll3,	1,	0,	0),
 	F_SLEW( 523200000, 1046400000,	  gpll3,	1,	0,	0),
 	F_SLEW( 550000000, 1100000000,	  gpll3,	1,	0,	0),
 	F_SLEW( 598000000, 1196000000,	  gpll3,	1,	0,	0),
@@ -871,6 +875,28 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_oxili_gfx3d_clk_qm215[] = {
+	F_SLEW( 19200000,  FIXED_CLK_SRC, xo,		1,	0,	0),
+	F_SLEW( 50000000,  FIXED_CLK_SRC, gpll0_gfx,	16,	0,	0),
+	F_SLEW( 80000000,  FIXED_CLK_SRC, gpll0_gfx,	10,	0,	0),
+	F_SLEW( 100000000, FIXED_CLK_SRC, gpll0_gfx,	8,	0,	0),
+	F_SLEW( 160000000, FIXED_CLK_SRC, gpll0_gfx,	5,	0,	0),
+	F_SLEW( 200000000, FIXED_CLK_SRC, gpll0_gfx,	4,	0,	0),
+	F_SLEW( 228570000, FIXED_CLK_SRC, gpll0_gfx,	3.5,	0,	0),
+	F_SLEW( 240000000, FIXED_CLK_SRC, gpll6_gfx,	4.5,	0,	0),
+	F_SLEW( 266670000, FIXED_CLK_SRC, gpll0_gfx,	3,	0,	0),
+	F_SLEW( 270000000, FIXED_CLK_SRC, gpll6_gfx,	4,	0,	0),
+	F_SLEW( 320000000, FIXED_CLK_SRC, gpll0_gfx,	2.5,	0,	0),
+	F_SLEW( 400000000, FIXED_CLK_SRC, gpll0_gfx,	2,	0,	0),
+	F_SLEW( 465000000, 930000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 484800000, 969600000,	  gpll3,	1,	0,	0),
+	F_SLEW( 500000000, 1000000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 523200000, 1046400000,	  gpll3,	1,	0,	0),
+	F_SLEW( 550000000, 1100000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 598000000, 1196000000,	  gpll3,	1,	0,	0),
+	F_END
+};
+
 static struct  rcg_clk gfx3d_clk_src = {
 	.cmd_rcgr_reg = GFX3D_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -4386,6 +4412,7 @@
 	bool compat_bin4 = false;
 	bool compat_bin5 = false;
 	bool compat_bin6 = false;
+	bool compat_bin7 = false;
 
 	compat_bin = of_device_is_compatible(pdev->dev.of_node,
 						"qcom,gcc-8937");
@@ -4405,11 +4432,14 @@
 	compat_bin6 = of_device_is_compatible(pdev->dev.of_node,
 						"qcom,gcc-sdm439");
 
+	compat_bin7 = of_device_is_compatible(pdev->dev.of_node,
+						"qcom,gcc-qm215");
+
 	ret = vote_bimc(&bimc_clk, INT_MAX);
 	if (ret < 0)
 		return ret;
 
-	if (compat_bin2 || compat_bin4 || compat_bin5)
+	if (compat_bin2 || compat_bin4 || compat_bin5 || compat_bin7)
 		nbases = APCS_C0_PLL_BASE;
 
 	if (compat_bin5 || compat_bin6) {
@@ -4442,7 +4472,7 @@
 		return PTR_ERR(vdd_dig.regulator[0]);
 	}
 
-	if (!compat_bin2 && !compat_bin4 && !compat_bin5) {
+	if (!compat_bin2 && !compat_bin4 && !compat_bin5 && !compat_bin7) {
 		vdd_sr2_pll.regulator[0] = devm_regulator_get(&pdev->dev,
 							"vdd_sr2_pll");
 		if (IS_ERR(vdd_sr2_pll.regulator[0])) {
@@ -4536,7 +4566,7 @@
 								475000000;
 			}
 		}
-	} else if (compat_bin2 || compat_bin4) {
+	} else if (compat_bin2 || compat_bin4 || compat_bin7) {
 		gpll0_clk_src.c.parent = &gpll0_clk_src_8937.c;
 		gpll0_ao_clk_src.c.parent = &gpll0_ao_clk_src_8937.c;
 		vdd_dig.num_levels = VDD_DIG_NUM_8917;
@@ -4546,6 +4576,9 @@
 		get_speed_bin(pdev, &speed_bin);
 		override_for_8917(speed_bin);
 
+		if (compat_bin7)
+			OVERRIDE_FTABLE(gfx3d, ftbl_gcc_oxili_gfx3d_clk, qm215);
+
 		if (compat_bin2) {
 			blsp1_qup2_spi_apps_clk_src.freq_tbl =
 				ftbl_gcc_blsp1_2_qup1_4_spi_apps_clk_8917;
@@ -4575,7 +4608,7 @@
 		ret = of_msm_clock_register(pdev->dev.of_node,
 					msm_clocks_lookup_8937,
 					ARRAY_SIZE(msm_clocks_lookup_8937));
-	else if (compat_bin2)
+	else if (compat_bin2 || compat_bin7)
 		ret = of_msm_clock_register(pdev->dev.of_node,
 					msm_clocks_lookup_8917,
 					ARRAY_SIZE(msm_clocks_lookup_8917));
@@ -4648,6 +4681,7 @@
 	{ .compatible = "qcom,gcc-8920" },
 	{ .compatible = "qcom,gcc-sdm439" },
 	{ .compatible = "qcom,gcc-sdm429" },
+	{ .compatible = "qcom,gcc-qm215" },
 	{}
 };
 
diff --git a/drivers/clk/msm/clock-local2.c b/drivers/clk/msm/clock-local2.c
index f200d0b..eaaa5ab 100644
--- a/drivers/clk/msm/clock-local2.c
+++ b/drivers/clk/msm/clock-local2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 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
@@ -1486,8 +1486,8 @@
 {
 	struct rcg_clk *rcg = to_rcg_clk(clk);
 	struct clk_freq_tbl *pixel_freq = rcg->current_freq;
-	int frac_num[] = {3, 2, 4, 1};
-	int frac_den[] = {8, 9, 9, 1};
+	int frac_num[] = {1, 3, 2, 4};
+	int frac_den[] = {1, 8, 9, 9};
 	int delta = 100000;
 	int i, rc;
 
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index aa8dccc..97a86ea 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -1436,6 +1436,13 @@
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
+	.max_register = 0x1c0,
+};
+
+static struct regmap_config dsi_phy_10nm_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
 	.max_register = 0x7c0,
 };
 
@@ -2139,26 +2146,26 @@
 		dsi0pll_shadow_pll_out_div.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi0pll_bitclk_src.clkr.regmap = rmap;
 		dsi0pll_shadow_bitclk_src.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi0pll_pclk_src.clkr.regmap = rmap;
 		dsi0pll_shadow_pclk_src.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi0pll_pclk_mux.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi0pll_pclk_src_mux.clkr.regmap = rmap;
 		dsi0pll_shadow_pclk_src_mux.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi0pll_byteclk_mux.clkr.regmap = rmap;
 
 		dsi0pll_vco_clk.priv = pll_res;
@@ -2186,26 +2193,26 @@
 		dsi1pll_shadow_pll_out_div.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi1pll_bitclk_src.clkr.regmap = rmap;
 		dsi1pll_shadow_bitclk_src.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi1pll_pclk_src.clkr.regmap = rmap;
 		dsi1pll_shadow_pclk_src.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi1pll_pclk_mux.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi1pll_pclk_src_mux.clkr.regmap = rmap;
 		dsi1pll_shadow_pclk_src_mux.clkr.regmap = rmap;
 
 		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
-				pll_res, &dsi_pll_10nm_config);
+				pll_res, &dsi_phy_10nm_config);
 		dsi1pll_byteclk_mux.clkr.regmap = rmap;
 
 		dsi1pll_vco_clk.priv = pll_res;
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index 3c90fe5..d13d889 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, 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
@@ -1798,7 +1798,7 @@
 	if (ice_dev == ERR_PTR(-EPROBE_DEFER))
 		return -EPROBE_DEFER;
 
-	if (!ice_dev)
+	if (!ice_dev || (ice_dev->is_ice_enabled == false))
 		return ret;
 
 	if (enable)
diff --git a/drivers/gpu/drm/bridge/lt9611.c b/drivers/gpu/drm/bridge/lt9611.c
index dd2d54f..8583b5b 100644
--- a/drivers/gpu/drm/bridge/lt9611.c
+++ b/drivers/gpu/drm/bridge/lt9611.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -1126,7 +1126,7 @@
 		lt9611_hdmi_tx_digital(pdata, cfg);
 		lt9611_hdmi_tx_phy(pdata, cfg);
 
-		msleep(500);
+		msleep(80);
 
 		lt9611_video_check(pdata);
 		lt9611_hdmi_output_enable(pdata);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
index cdcb331..9f81ed1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -261,13 +261,13 @@
 int dsi_deregister_clk_handle(void *client);
 
 /**
- * dsi_display_link_clk_force_update_ctrl() - force to set link clks
+ * dsi_display_link_clk_force_update() - force to set link clks
  * @handle:     Handle of desired DSI clock client.
  *
  * return: error code in case of failure or 0 for success.
  */
 
-int dsi_display_link_clk_force_update_ctrl(void *handle);
+int dsi_display_link_clk_force_update(void *handle);
 
 /**
  * dsi_display_clk_ctrl() - set frequencies for link clks
@@ -277,7 +277,8 @@
  *
  * return: error code in case of failure or 0 for success.
  */
-int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state);
+int dsi_display_clk_ctrl(void *handle, enum dsi_clk_type clk_type,
+			 enum dsi_clk_state clk_state);
 
 /**
  * dsi_clk_set_link_frequencies() - set frequencies for link clks
@@ -331,4 +332,14 @@
  * @clk:       list of src clocks.
  */
 void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk);
+
+/**
+ * dsi_clk_req_state() - request to change dsi clock state
+ * @client:       DSI clocl client pointer.
+ * @clk:          DSI clock list.
+ * @state:        Requested state of the clock.
+ */
+int dsi_clk_req_state(void *client, enum dsi_clk_type clk,
+	enum dsi_clk_state state);
+
 #endif /* _DSI_CLK_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
index 9592603f..2faccad 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -1255,9 +1255,7 @@
 	return rc;
 }
 
-DEFINE_MUTEX(dsi_mngr_clk_mutex);
-
-static int dsi_display_link_clk_force_update(void *client)
+int dsi_display_link_clk_force_update(void *client)
 {
 	int rc = 0;
 	struct dsi_clk_client_info *c = client;
@@ -1304,42 +1302,6 @@
 
 }
 
-int dsi_display_link_clk_force_update_ctrl(void *handle)
-{
-	int rc = 0;
-
-	if (!handle) {
-		pr_err("%s: Invalid arg\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&dsi_mngr_clk_mutex);
-
-	rc = dsi_display_link_clk_force_update(handle);
-
-	mutex_unlock(&dsi_mngr_clk_mutex);
-
-	return rc;
-}
-
-int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state)
-{
-	int rc = 0;
-
-	if (!handle) {
-		pr_err("%s: Invalid arg\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&dsi_mngr_clk_mutex);
-	rc = dsi_clk_req_state(handle, clk_type, clk_state);
-	if (rc)
-		pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
-	mutex_unlock(&dsi_mngr_clk_mutex);
-
-	return rc;
-}
-
 void *dsi_register_clk_handle(void *clk_mngr, char *client)
 {
 	void *handle = NULL;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 378ef4c..7e3021d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -891,6 +891,7 @@
 	int rc = 0;
 	u8 *buf = NULL;
 	u32 len, i;
+	u8 cmd_type = 0;
 
 	len = packet->size;
 	len += 0x3; len &= ~0x03; /* Align to 32 bits */
@@ -913,7 +914,11 @@
 
 
 	/* send embedded BTA for read commands */
-	if ((buf[2] & 0x3f) == MIPI_DSI_DCS_READ)
+	cmd_type = buf[2] & 0x3f;
+	if ((cmd_type == MIPI_DSI_DCS_READ) ||
+	    (cmd_type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) ||
+	    (cmd_type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) ||
+	    (cmd_type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM))
 		buf[3] |= BIT(5);
 
 	*buffer = buf;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index f8170b2..79e3b75 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -45,6 +45,9 @@
 
 static DEFINE_MUTEX(dsi_display_list_lock);
 static LIST_HEAD(dsi_display_list);
+
+static DEFINE_MUTEX(dsi_display_clk_mutex);
+
 static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
 static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN];
 static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY];
@@ -4515,6 +4518,43 @@
 	return rc;
 }
 
+static int dsi_display_link_clk_force_update_ctrl(void *handle)
+{
+	int rc = 0;
+
+	if (!handle) {
+		pr_err("%s: Invalid arg\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dsi_display_clk_mutex);
+
+	rc = dsi_display_link_clk_force_update(handle);
+
+	mutex_unlock(&dsi_display_clk_mutex);
+
+	return rc;
+}
+
+int dsi_display_clk_ctrl(void *handle,
+	enum dsi_clk_type clk_type, enum dsi_clk_state clk_state)
+{
+	int rc = 0;
+
+	if (!handle) {
+		pr_err("%s: Invalid arg\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dsi_display_clk_mutex);
+	rc = dsi_clk_req_state(handle, clk_type, clk_state);
+	if (rc)
+		pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
+	mutex_unlock(&dsi_display_clk_mutex);
+
+	return rc;
+}
+
 static int dsi_display_force_update_dsi_clk(struct dsi_display *display)
 {
 	int rc = 0;
@@ -4603,6 +4643,7 @@
 
 	mutex_lock(&display->display_lock);
 
+	mutex_lock(&dsi_display_clk_mutex);
 	display->cached_clk_rate = clk_rate;
 	rc = dsi_display_update_dsi_bitrate(display, clk_rate);
 	if (!rc) {
@@ -4615,12 +4656,14 @@
 		atomic_set(&display->clkrate_change_pending, 0);
 		display->cached_clk_rate = 0;
 
+		mutex_unlock(&dsi_display_clk_mutex);
 		mutex_unlock(&display->display_lock);
 
 		return rc;
 	}
 	atomic_set(&display->clkrate_change_pending, 1);
 
+	mutex_unlock(&dsi_display_clk_mutex);
 	mutex_unlock(&display->display_lock);
 
 	return count;
@@ -5458,13 +5501,13 @@
 	cfg = &(display->panel->host_config);
 	bpp = dsi_pixel_format_to_bpp(cfg->dst_format);
 
-	if (cfg->data_lanes & DSI_LOGICAL_LANE_0)
+	if (cfg->data_lanes & DSI_DATA_LANE_0)
 		lanes++;
-	if (cfg->data_lanes & DSI_LOGICAL_LANE_1)
+	if (cfg->data_lanes & DSI_DATA_LANE_1)
 		lanes++;
-	if (cfg->data_lanes & DSI_LOGICAL_LANE_2)
+	if (cfg->data_lanes & DSI_DATA_LANE_2)
 		lanes++;
-	if (cfg->data_lanes & DSI_LOGICAL_LANE_3)
+	if (cfg->data_lanes & DSI_DATA_LANE_3)
 		lanes++;
 
 	dsi_display_get_mode_count_no_lock(display, &total_modes);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 68a7277..edad45f 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -206,7 +206,8 @@
 	}
 
 	if (c_bridge->dsi_mode.dsi_mode_flags &
-			(DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR)) {
+			(DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR |
+			 DSI_MODE_FLAG_DYN_CLK)) {
 		pr_debug("[%d] seamless enable\n", c_bridge->id);
 		return;
 	}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index b43b23c..1a29b0e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -1177,7 +1177,7 @@
 	int rc = 0;
 	bool supported = false;
 	const char *type;
-	u32 val = 0, i;
+	u32 i;
 
 	supported = of_property_read_bool(of_node,
 					"qcom,mdss-dsi-pan-enable-dynamic-fps");
@@ -1237,11 +1237,10 @@
 	dfps_caps->dfps_support = true;
 
 	/* calculate max and min fps */
-	of_property_read_u32(of_node, "qcom,mdss-dsi-panel-framerate", &val);
-	dfps_caps->max_refresh_rate = val;
-	dfps_caps->min_refresh_rate = val;
+	dfps_caps->max_refresh_rate = dfps_caps->dfps_list[0];
+	dfps_caps->min_refresh_rate = dfps_caps->dfps_list[0];
 
-	for (i = 0; i < dfps_caps->dfps_list_len; i++) {
+	for (i = 1; i < dfps_caps->dfps_list_len; i++) {
 		if (dfps_caps->dfps_list[i] < dfps_caps->min_refresh_rate)
 			dfps_caps->min_refresh_rate = dfps_caps->dfps_list[i];
 		else if (dfps_caps->dfps_list[i] > dfps_caps->max_refresh_rate)
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 0f5e127..122f319 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -2708,6 +2708,21 @@
 	_sde_encoder_virt_enable_helper(drm_enc);
 }
 
+static void sde_encoder_off_work(struct kthread_work *work)
+{
+	struct sde_encoder_virt *sde_enc = container_of(work,
+			struct sde_encoder_virt, delayed_off_work.work);
+	struct drm_encoder *drm_enc;
+
+	if (!sde_enc) {
+		SDE_ERROR("invalid sde encoder\n");
+		return;
+	}
+	drm_enc = &sde_enc->base;
+
+	sde_encoder_idle_request(drm_enc);
+}
+
 static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
 {
 	struct sde_encoder_virt *sde_enc = NULL;
@@ -2768,6 +2783,11 @@
 			sde_enc->input_handler_registered = true;
 	}
 
+	if (!(msm_is_mode_seamless_vrr(cur_mode)
+			|| msm_is_mode_seamless_dms(cur_mode)))
+		kthread_init_delayed_work(&sde_enc->delayed_off_work,
+			sde_encoder_off_work);
+
 	ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
 	if (ret) {
 		SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n",
@@ -3094,21 +3114,6 @@
 	return 0;
 }
 
-static void sde_encoder_off_work(struct kthread_work *work)
-{
-	struct sde_encoder_virt *sde_enc = container_of(work,
-			struct sde_encoder_virt, delayed_off_work.work);
-	struct drm_encoder *drm_enc;
-
-	if (!sde_enc) {
-		SDE_ERROR("invalid sde encoder\n");
-		return;
-	}
-	drm_enc = &sde_enc->base;
-
-	sde_encoder_idle_request(drm_enc);
-}
-
 /**
  * _sde_encoder_trigger_flush - trigger flush for a physical encoder
  * drm_enc: Pointer to drm encoder structure
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index c237f27..6cbd663 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -3291,6 +3291,13 @@
 	if (rc)
 		SDE_DEBUG("sde splash data fetch failed: %d\n", rc);
 
+	for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
+		priv->phandle.data_bus_handle[i].ab_rt =
+			SDE_POWER_HANDLE_CONT_SPLASH_BUS_AB_QUOTA;
+		priv->phandle.data_bus_handle[i].ib_rt =
+			SDE_POWER_HANDLE_CONT_SPLASH_BUS_IB_QUOTA;
+	}
+
 	rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
 		true);
 	if (rc) {
diff --git a/drivers/gpu/drm/msm/sde_hdcp_1x.c b/drivers/gpu/drm/msm/sde_hdcp_1x.c
index 2c7f52c..53e20e2 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_1x.c
+++ b/drivers/gpu/drm/msm/sde_hdcp_1x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2019, 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
@@ -1263,6 +1263,8 @@
 
 	hdcp->sink_r0_ready = false;
 
+	hdcp1_unload_app();
+
 	pr_debug("%s: HDCP: Off\n", SDE_HDCP_STATE_NAME);
 } /* hdcp_1x_off */
 
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index b74d48c..892c800 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -982,6 +982,7 @@
 static int a6xx_send_cp_init(struct adreno_device *adreno_dev,
 			 struct adreno_ringbuffer *rb)
 {
+	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	unsigned int *cmds;
 	int ret;
 
@@ -994,10 +995,17 @@
 	_set_ordinals(adreno_dev, cmds, 11);
 
 	ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
-	if (ret)
+	if (ret) {
 		adreno_spin_idle_debug(adreno_dev,
 				"CP initialization failed to idle\n");
 
+		if (!adreno_is_a3xx(adreno_dev))
+			kgsl_sharedmem_writel(device, &device->scratch,
+					SCRATCH_RPTR_OFFSET(rb->id), 0);
+		rb->wptr = 0;
+		rb->_wptr = 0;
+	}
+
 	return ret;
 }
 
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 4cf6250..87e1431 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2050,6 +2050,8 @@
 {
 	u64 val;
 	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
+	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
+
 	/*
 	 * We cannot enable or disable the clocks in interrupt context, this
 	 * function is called from interrupt context if there is an axi error
@@ -2057,9 +2059,11 @@
 	if (in_interrupt())
 		return 0;
 
+	if (ctx->regbase == NULL)
+		return 0;
+
 	kgsl_iommu_enable_clk(mmu);
-	val = KGSL_IOMMU_GET_CTX_REG_Q(&iommu->ctx[KGSL_IOMMU_CONTEXT_USER],
-					TTBR0);
+	val = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0);
 	kgsl_iommu_disable_clk(mmu);
 	return val;
 }
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 7256647..fbd952a 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -146,26 +146,15 @@
 static int uhid_hid_open(struct hid_device *hid)
 {
 	struct uhid_device *uhid = hid->driver_data;
-	int retval = 0;
 
-	mutex_lock(&uhid_open_mutex);
-	if (!hid->open++) {
-		retval = uhid_queue_event(uhid, UHID_OPEN);
-		if (retval)
-			hid->open--;
-	}
-	mutex_unlock(&uhid_open_mutex);
-	return retval;
+	return uhid_queue_event(uhid, UHID_OPEN);
 }
 
 static void uhid_hid_close(struct hid_device *hid)
 {
 	struct uhid_device *uhid = hid->driver_data;
 
-	mutex_lock(&uhid_open_mutex);
-	if (!--hid->open)
-		uhid_queue_event(uhid, UHID_CLOSE);
-	mutex_unlock(&uhid_open_mutex);
+	uhid_queue_event(uhid, UHID_CLOSE);
 }
 
 static int uhid_hid_parse(struct hid_device *hid)
diff --git a/drivers/iio/imu/inv_mpu/Kconfig b/drivers/iio/imu/inv_mpu/Kconfig
index 7505454..d729e3a 100644
--- a/drivers/iio/imu/inv_mpu/Kconfig
+++ b/drivers/iio/imu/inv_mpu/Kconfig
@@ -60,4 +60,11 @@
 	  This driver can be built as a module. The module will be called
 	  inv-mpu-iio-spi.
 
+config ENABLE_IAM_ACC_GYRO_BUFFERING
+	bool "Enable accel & gyro  boot time sensor sample buffering"
+	depends on INV_MPU_IIO
+	help
+	  Say Y here if you want to buffer boot time sensor
+	  samples for IAM20680 accelerometer and gyroscope
+
 source "drivers/iio/imu/inv_mpu/inv_test/Kconfig"
diff --git a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c
index b429f57..f8d13cc 100644
--- a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c
+++ b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c
@@ -311,6 +311,26 @@
 	return result;
 }
 
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+static inline int inv_check_acc_gyro_early_buff_enable_flag(
+		struct iio_dev *indio_dev)
+{
+	struct inv_mpu_state *st = iio_priv(indio_dev);
+
+	if (st->acc_buffer_inv_samples == true ||
+			st->gyro_buffer_inv_samples == true)
+		return 1;
+	else
+		return 0;
+}
+#else
+static inline int inv_check_acc_gyro_early_buff_enable_flag(
+		struct iio_dev *indio_dev)
+{
+	return 0;
+}
+#endif
+
 /*
  * inv_misc_attr_store() -  calling this function
  */
@@ -321,6 +341,9 @@
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	int result;
 
+	if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev))
+		return count;
+
 	mutex_lock(&indio_dev->mlock);
 	result = _misc_attr_store(dev, attr, buf, count);
 	mutex_unlock(&indio_dev->mlock);
@@ -351,6 +374,9 @@
 	int data, rate, ind;
 	int result;
 
+	if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev))
+		return count;
+
 	result = kstrtoint(buf, 10, &data);
 	if (result)
 		return -EINVAL;
@@ -398,6 +424,9 @@
 	int data, on, ind;
 	int result;
 
+	if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev))
+		return count;
+
 	result = kstrtoint(buf, 10, &data);
 	if (result)
 		return -EINVAL;
@@ -493,7 +522,7 @@
 			p1[0] = ((power_on_data >> 16) & 0xff);
 			p1[1] = ((power_on_data >> 24) & 0xff);
 
-			if (st->bus_type == BUS_SPI) {
+			if (st->bus_type == BUS_IIO_SPI) {
 				struct spi_transfer power_on;
 				struct spi_message msg;
 
@@ -508,7 +537,7 @@
 				spi_message_add_tail(&power_on, &msg);
 				spi_sync(to_spi_device(st->dev), &msg);
 
-			} else if (st->bus_type == BUS_I2C) {
+			} else if (st->bus_type == BUS_IIO_I2C) {
 				struct i2c_msg msgs[2];
 
 				p0[0] &= 0x7f;
@@ -579,6 +608,9 @@
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	int result;
 
+	if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev))
+		return count;
+
 	mutex_lock(&indio_dev->mlock);
 	result = _basic_attr_store(dev, attr, buf, count);
 
@@ -717,7 +749,7 @@
 		return res;
 	mutex_unlock(&indio_dev->mlock);
 
-	temp = (s32)be16_to_cpup((__be16 *)(data)) * 10000;
+	temp = (s16)be16_to_cpup((__be16 *)(data)) * 10000;
 	temp = temp / TEMP_SENSITIVITY + TEMP_OFFSET;
 
 	return snprintf(buf, MAX_WR_SZ, "%d %lld\n", temp, get_time_ns());
@@ -771,6 +803,169 @@
 	return count;
 }
 
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+static int inv_gyro_read_bootsampl(struct inv_mpu_state *st,
+		unsigned long enable_read)
+{
+	int i = 0;
+
+	if (enable_read) {
+		st->gyro_buffer_inv_samples = false;
+		for (i = 0; i < st->gyro_bufsample_cnt; i++) {
+			dev_dbg(st->dev, "gyro_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n",
+					i, st->inv_gyro_samplist[i]->xyz[0],
+					st->inv_gyro_samplist[i]->xyz[1],
+					st->inv_gyro_samplist[i]->xyz[2],
+					st->inv_gyro_samplist[i]->tsec,
+					st->inv_gyro_samplist[i]->tnsec);
+			input_report_abs(st->gyrobuf_dev, ABS_X,
+					st->inv_gyro_samplist[i]->xyz[0]);
+			input_report_abs(st->gyrobuf_dev, ABS_Y,
+					st->inv_gyro_samplist[i]->xyz[1]);
+			input_report_abs(st->gyrobuf_dev, ABS_Z,
+					st->inv_gyro_samplist[i]->xyz[2]);
+			input_report_abs(st->gyrobuf_dev, ABS_RX,
+					st->inv_gyro_samplist[i]->tsec);
+			input_report_abs(st->gyrobuf_dev, ABS_RY,
+					st->inv_gyro_samplist[i]->tnsec);
+			input_sync(st->gyrobuf_dev);
+		}
+	} else {
+		/* clean up */
+		if (st->gyro_bufsample_cnt != 0) {
+			for (i = 0; i < INV_GYRO_MAXSAMPLE; i++)
+				kmem_cache_free(st->inv_gyro_cachepool,
+						st->inv_gyro_samplist[i]);
+			kmem_cache_destroy(st->inv_gyro_cachepool);
+			st->gyro_bufsample_cnt = 0;
+		}
+
+	}
+	/*SYN_CONFIG indicates end of data*/
+	input_event(st->gyrobuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF);
+	input_sync(st->gyrobuf_dev);
+	dev_dbg(st->dev, "End of gyro samples bufsample_cnt=%d\n",
+			st->gyro_bufsample_cnt);
+	return 0;
+}
+static int inv_acc_read_bootsampl(struct inv_mpu_state *st,
+		unsigned long enable_read)
+{
+	int i = 0;
+
+	if (enable_read) {
+		st->acc_buffer_inv_samples = false;
+		for (i = 0; i < st->acc_bufsample_cnt; i++) {
+			dev_dbg(st->dev, "acc_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n",
+					i, st->inv_acc_samplist[i]->xyz[0],
+					st->inv_acc_samplist[i]->xyz[1],
+					st->inv_acc_samplist[i]->xyz[2],
+					st->inv_acc_samplist[i]->tsec,
+					st->inv_acc_samplist[i]->tnsec);
+			input_report_abs(st->accbuf_dev, ABS_X,
+					st->inv_acc_samplist[i]->xyz[0]);
+			input_report_abs(st->accbuf_dev, ABS_Y,
+					st->inv_acc_samplist[i]->xyz[1]);
+			input_report_abs(st->accbuf_dev, ABS_Z,
+					st->inv_acc_samplist[i]->xyz[2]);
+			input_report_abs(st->accbuf_dev, ABS_RX,
+					st->inv_acc_samplist[i]->tsec);
+			input_report_abs(st->accbuf_dev, ABS_RY,
+					st->inv_acc_samplist[i]->tnsec);
+			input_sync(st->accbuf_dev);
+		}
+	} else {
+		/* clean up */
+		if (st->acc_bufsample_cnt != 0) {
+			for (i = 0; i < INV_ACC_MAXSAMPLE; i++)
+				kmem_cache_free(st->inv_acc_cachepool,
+						st->inv_acc_samplist[i]);
+			kmem_cache_destroy(st->inv_acc_cachepool);
+			st->acc_bufsample_cnt = 0;
+		}
+
+	}
+	/*SYN_CONFIG indicates end of data*/
+	input_event(st->accbuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF);
+	input_sync(st->accbuf_dev);
+	dev_dbg(st->dev, "End of acc samples bufsample_cnt=%d\n",
+			st->acc_bufsample_cnt);
+	return 0;
+}
+
+static ssize_t read_gyro_boot_sample_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct inv_mpu_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, MAX_WR_SZ, "%d\n",
+			st->read_gyro_boot_sample);
+}
+
+static ssize_t read_gyro_boot_sample_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int err;
+	unsigned long enable = 0;
+
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct inv_mpu_state *st = iio_priv(indio_dev);
+
+	err = kstrtoul(buf, 10, &enable);
+	if (err)
+		return err;
+	if (enable > 1) {
+		dev_err(st->dev,
+				"Invalid value of input, input=%ld\n", enable);
+		return -EINVAL;
+	}
+	err = inv_gyro_read_bootsampl(st, enable);
+	if (err)
+		return err;
+	st->read_gyro_boot_sample = enable;
+	return count;
+
+}
+
+static ssize_t read_acc_boot_sample_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct inv_mpu_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, MAX_WR_SZ, "%d\n",
+			st->read_acc_boot_sample);
+}
+static ssize_t read_acc_boot_sample_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int err;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct inv_mpu_state *st = iio_priv(indio_dev);
+
+	unsigned long enable = 0;
+
+	err = kstrtoul(buf, 10, &enable);
+	if (err)
+		return err;
+	if (enable > 1) {
+		dev_err(st->dev,
+				"Invalid value of input, input=%ld\n", enable);
+		return -EINVAL;
+	}
+	err = inv_acc_read_bootsampl(st, enable);
+	if (err)
+		return err;
+	st->read_acc_boot_sample = enable;
+	return count;
+}
+#endif
+
 static const struct iio_chan_spec inv_mpu_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(INV_MPU_SCAN_TIMESTAMP),
 };
@@ -780,6 +975,12 @@
 static DEVICE_ATTR(out_temperature, S_IRUGO | S_IWUSR,
 			inv_temperature_show, NULL);
 static DEVICE_ATTR(misc_self_test, S_IRUGO | S_IWUSR, inv_self_test, NULL);
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+static IIO_DEVICE_ATTR(read_acc_boot_sample, 0644,
+	read_acc_boot_sample_show, read_acc_boot_sample_store, SENSOR_L_ACCEL);
+static IIO_DEVICE_ATTR(read_gyro_boot_sample, 0644,
+	read_gyro_boot_sample_show, read_gyro_boot_sample_store, SENSOR_L_GYRO);
+#endif
 
 static IIO_DEVICE_ATTR(info_anglvel_matrix, S_IRUGO, inv_attr_show, NULL,
 			ATTR_GYRO_MATRIX);
@@ -914,6 +1115,10 @@
 #ifndef SUPPORT_ONLY_BASIC_FEATURES
 	&iio_dev_attr_in_power_on.dev_attr.attr,
 #endif
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+	&iio_dev_attr_read_acc_boot_sample.dev_attr.attr,
+	&iio_dev_attr_read_gyro_boot_sample.dev_attr.attr,
+#endif
 	&iio_dev_attr_in_accel_enable.dev_attr.attr,
 	&iio_dev_attr_in_accel_wake_enable.dev_attr.attr,
 	&iio_dev_attr_info_accel_matrix.dev_attr.attr,
diff --git a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_setup_20680.c b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_setup_20680.c
index 5e9cf89..b3ae5dd 100644
--- a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_setup_20680.c
+++ b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_setup_20680.c
@@ -271,6 +271,9 @@
 	u64 timeout;
 	int required_fifo_size;
 
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+	st->batch.timeout = 100;
+#endif
 	if (st->batch.timeout) {
 		required_fifo_size = st->batch.timeout * st->eng_info[ENGINE_GYRO].running_rate
 					* st->batch.pk_size / 1000;
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c
index e7838fc..65089f2 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c
@@ -278,6 +278,220 @@
 	return res;
 }
 
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+static void inv_enable_acc_gyro(struct inv_mpu_state *st)
+{
+	struct iio_dev *indio_dev = iio_priv_to_dev(st);
+	int accel_hz = 100;
+	int gyro_hz = 100;
+
+	/**Enable the ACCEL**/
+	st->sensor_l[SENSOR_L_ACCEL].on = 0;
+	st->trigger_state = RATE_TRIGGER;
+	inv_check_sensor_on(st);
+	set_inv_enable(indio_dev);
+
+	inv_switch_power_in_lp(st, true);
+	st->chip_config.accel_fs = ACCEL_FSR_2G;
+	inv_set_accel_sf(st);
+	st->trigger_state = MISC_TRIGGER;
+	set_inv_enable(indio_dev);
+
+	st->sensor_l[SENSOR_L_ACCEL].rate = accel_hz;
+	st->trigger_state = DATA_TRIGGER;
+	inv_check_sensor_on(st);
+	set_inv_enable(indio_dev);
+
+	st->sensor_l[SENSOR_L_ACCEL].on = 1;
+	st->trigger_state = RATE_TRIGGER;
+	inv_check_sensor_on(st);
+	set_inv_enable(indio_dev);
+
+	/**Enable the GYRO**/
+	st->sensor_l[SENSOR_L_GYRO].on = 0;
+	st->trigger_state = RATE_TRIGGER;
+	inv_check_sensor_on(st);
+	set_inv_enable(indio_dev);
+
+	inv_switch_power_in_lp(st, true);
+	st->chip_config.fsr = GYRO_FSR_250DPS;
+	inv_set_gyro_sf(st);
+	st->trigger_state = MISC_TRIGGER;
+	set_inv_enable(indio_dev);
+
+	st->sensor_l[SENSOR_L_GYRO].rate = gyro_hz;
+	st->trigger_state = DATA_TRIGGER;
+	inv_check_sensor_on(st);
+	set_inv_enable(indio_dev);
+
+	st->sensor_l[SENSOR_L_GYRO].on = 1;
+	st->trigger_state = RATE_TRIGGER;
+	inv_check_sensor_on(st);
+	set_inv_enable(indio_dev);
+}
+
+static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev)
+{
+	int i = 0, err = 0;
+	struct inv_mpu_state *st;
+
+	st = iio_priv(indio_dev);
+	st->acc_bufsample_cnt = 0;
+	st->gyro_bufsample_cnt = 0;
+	st->report_evt_cnt = 5;
+	st->max_buffer_time = 40;
+
+	st->inv_acc_cachepool = kmem_cache_create("acc_sensor_sample",
+			sizeof(struct inv_acc_sample),
+			0,
+			SLAB_HWCACHE_ALIGN, NULL);
+	if (!st->inv_acc_cachepool) {
+		pr_err("inv_acc_cachepool cache create failed\n");
+		err = -ENOMEM;
+		return 0;
+	}
+
+	for (i = 0; i < INV_ACC_MAXSAMPLE; i++) {
+		st->inv_acc_samplist[i] =
+			kmem_cache_alloc(st->inv_acc_cachepool,
+					GFP_KERNEL);
+		if (!st->inv_acc_samplist[i]) {
+			err = -ENOMEM;
+			goto clean_exit1;
+		}
+	}
+
+	st->inv_gyro_cachepool = kmem_cache_create("gyro_sensor_sample"
+			, sizeof(struct inv_gyro_sample), 0,
+			SLAB_HWCACHE_ALIGN, NULL);
+	if (!st->inv_gyro_cachepool) {
+		pr_err("inv_gyro_cachepool cache create failed\n");
+		err = -ENOMEM;
+		goto clean_exit1;
+	}
+
+	for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) {
+		st->inv_gyro_samplist[i] =
+			kmem_cache_alloc(st->inv_gyro_cachepool,
+					GFP_KERNEL);
+		if (!st->inv_gyro_samplist[i]) {
+			err = -ENOMEM;
+			goto clean_exit2;
+		}
+	}
+
+	st->accbuf_dev = input_allocate_device();
+	if (!st->accbuf_dev) {
+		err = -ENOMEM;
+		pr_err("input device allocation failed\n");
+		goto clean_exit2;
+	}
+	st->accbuf_dev->name = "inv_accbuf";
+	st->accbuf_dev->id.bustype = BUS_I2C;
+	input_set_events_per_packet(st->accbuf_dev,
+			st->report_evt_cnt * INV_ACC_MAXSAMPLE);
+	set_bit(EV_ABS, st->accbuf_dev->evbit);
+	input_set_abs_params(st->accbuf_dev, ABS_X,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->accbuf_dev, ABS_Y,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->accbuf_dev, ABS_Z,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->accbuf_dev, ABS_RX,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->accbuf_dev, ABS_RY,
+			-G_MAX, G_MAX, 0, 0);
+	err = input_register_device(st->accbuf_dev);
+	if (err) {
+		pr_err("unable to register input device %s\n",
+				st->accbuf_dev->name);
+		goto clean_exit3;
+	}
+
+	st->gyrobuf_dev = input_allocate_device();
+	if (!st->gyrobuf_dev) {
+		err = -ENOMEM;
+		pr_err("input device allocation failed\n");
+		goto clean_exit4;
+	}
+	st->gyrobuf_dev->name = "inv_gyrobuf";
+	st->gyrobuf_dev->id.bustype = BUS_I2C;
+	input_set_events_per_packet(st->gyrobuf_dev,
+			st->report_evt_cnt * INV_GYRO_MAXSAMPLE);
+	set_bit(EV_ABS, st->gyrobuf_dev->evbit);
+	input_set_abs_params(st->gyrobuf_dev, ABS_X,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->gyrobuf_dev, ABS_Y,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->gyrobuf_dev, ABS_Z,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->gyrobuf_dev, ABS_RX,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(st->gyrobuf_dev, ABS_RY,
+			-G_MAX, G_MAX, 0, 0);
+	err = input_register_device(st->gyrobuf_dev);
+	if (err) {
+		pr_err("unable to register input device %s\n",
+				st->gyrobuf_dev->name);
+		goto clean_exit5;
+	}
+
+	st->acc_buffer_inv_samples = true;
+	st->gyro_buffer_inv_samples = true;
+
+	inv_enable_acc_gyro(st);
+
+	return 1;
+
+clean_exit5:
+	input_free_device(st->gyrobuf_dev);
+clean_exit4:
+	input_unregister_device(st->accbuf_dev);
+clean_exit3:
+	input_free_device(st->accbuf_dev);
+clean_exit2:
+	for (i = 0; i < INV_GYRO_MAXSAMPLE; i++)
+		kmem_cache_free(st->inv_gyro_cachepool,
+				st->inv_gyro_samplist[i]);
+	kmem_cache_destroy(st->inv_gyro_cachepool);
+clean_exit1:
+	for (i = 0; i < INV_ACC_MAXSAMPLE; i++)
+		kmem_cache_free(st->inv_acc_cachepool,
+				st->inv_acc_samplist[i]);
+	kmem_cache_destroy(st->inv_acc_cachepool);
+
+	return 0;
+}
+static void inv_acc_gyro_input_cleanup(
+		struct iio_dev *indio_dev)
+{
+	int i = 0;
+	struct inv_mpu_state *st;
+
+	st = iio_priv(indio_dev);
+	input_free_device(st->accbuf_dev);
+	input_unregister_device(st->gyrobuf_dev);
+	input_free_device(st->gyrobuf_dev);
+	for (i = 0; i < INV_GYRO_MAXSAMPLE; i++)
+		kmem_cache_free(st->inv_gyro_cachepool,
+				st->inv_gyro_samplist[i]);
+	kmem_cache_destroy(st->inv_gyro_cachepool);
+	for (i = 0; i < INV_ACC_MAXSAMPLE; i++)
+		kmem_cache_free(st->inv_acc_cachepool,
+				st->inv_acc_samplist[i]);
+	kmem_cache_destroy(st->inv_acc_cachepool);
+}
+#else
+static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev)
+{
+	return 1;
+}
+static void inv_acc_gyro_input_cleanup(
+		struct iio_dev *indio_dev)
+{
+}
+#endif
+
 /*
  *  inv_mpu_probe() - probe function.
  */
@@ -318,7 +532,7 @@
 	st->mem_write = inv_i2c_mem_write;
 	st->mem_read = inv_i2c_mem_read;
 	st->dev = &client->dev;
-	st->bus_type = BUS_I2C;
+	st->bus_type = BUS_IIO_I2C;
 #ifdef CONFIG_OF
 	result = invensense_mpu_parse_dt(st->dev, &st->plat_data);
 	if (result)
@@ -420,6 +634,9 @@
 #ifdef TIMER_BASED_BATCHING
 	pr_info("Timer based batching\n");
 #endif
+	result = inv_acc_gyro_early_buff_init(indio_dev);
+	if (!result)
+		return -EIO;
 
 	return 0;
 #ifdef KERNEL_VERSION_4_X
@@ -438,10 +655,10 @@
 out_unreg_ring:
 	inv_mpu_unconfigure_ring(indio_dev);
 out_free:
+	dev_err(st->dev, "%s failed %d\n", __func__, result);
 	iio_device_free(indio_dev);
 out_no_free:
 #endif
-	dev_err(st->dev, "%s failed %d\n", __func__, result);
 
 	return -EIO;
 }
@@ -479,6 +696,7 @@
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	struct inv_mpu_state *st = iio_priv(indio_dev);
 
+	inv_acc_gyro_input_cleanup(indio_dev);
 #ifdef KERNEL_VERSION_4_X
 	devm_iio_device_unregister(st->dev, indio_dev);
 #else
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu/inv_mpu_iio.h
index 9e73165..1e0a176 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_iio.h
@@ -37,7 +37,9 @@
 #include <linux/iio/sysfs.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/kfifo_buf.h>
-
+#include <linux/input.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
 #ifdef CONFIG_INV_MPU_IIO_ICM20648
 #include "icm20648/dmp3Default.h"
 #endif
@@ -131,9 +133,37 @@
 #define COVARIANCE_SIZE          14
 #define ACCEL_COVARIANCE_SIZE  (COVARIANCE_SIZE * sizeof(int))
 
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+#define INV_ACC_MAXSAMPLE        4000
+#define INV_GYRO_MAXSAMPLE       4000
+#define G_MAX                    23920640
+struct inv_acc_sample {
+	int xyz[3];
+	unsigned int tsec;
+	unsigned long long tnsec;
+};
+struct inv_gyro_sample {
+	int xyz[3];
+	unsigned int tsec;
+	unsigned long long tnsec;
+};
+enum {
+	ACCEL_FSR_2G = 0,
+	ACCEL_FSR_4G = 1,
+	ACCEL_FSR_8G = 2,
+	ACCEL_FSR_16G = 3
+};
+enum {
+	GYRO_FSR_250DPS = 0,
+	GYRO_FSR_500DPS = 1,
+	GYRO_FSR_1000DPS = 2,
+	GYRO_FSR_2000DPS = 3
+};
+#endif
+
 enum inv_bus_type {
-	BUS_I2C = 0,
-	BUS_SPI,
+	BUS_IIO_I2C = 0,
+	BUS_IIO_SPI,
 };
 
 struct inv_mpu_state;
@@ -825,6 +855,24 @@
 	u8 int_en_2;
 	u8 gesture_int_count;
 	u8 smplrt_div;
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+	bool read_acc_boot_sample;
+	bool read_gyro_boot_sample;
+	int acc_bufsample_cnt;
+	int gyro_bufsample_cnt;
+	bool acc_buffer_inv_samples;
+	bool gyro_buffer_inv_samples;
+	struct kmem_cache *inv_acc_cachepool;
+	struct kmem_cache *inv_gyro_cachepool;
+	struct inv_acc_sample *inv_acc_samplist[INV_ACC_MAXSAMPLE];
+	struct inv_gyro_sample *inv_gyro_samplist[INV_GYRO_MAXSAMPLE];
+	ktime_t timestamp;
+	int max_buffer_time;
+	struct input_dev *accbuf_dev;
+	struct input_dev *gyrobuf_dev;
+	int report_evt_cnt;
+#endif
+
 };
 
 /**
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu/inv_mpu_ring.c
index 3e5bccbe..de64b2c 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_ring.c
@@ -297,6 +297,80 @@
 
 	inv_push_8bytes_buffer(st, hdr, t, out);
 }
+#ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING
+static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t,
+						s16 x, s16 y, s16 z)
+{
+	if (false == st->acc_buffer_inv_samples)
+		return;
+	st->timestamp.tv64 = t;
+	if (ktime_to_timespec(st->timestamp).tv_sec
+			<  st->max_buffer_time) {
+		if (st->acc_bufsample_cnt < INV_ACC_MAXSAMPLE) {
+			st->inv_acc_samplist[st->
+				acc_bufsample_cnt]->xyz[0] = x;
+			st->inv_acc_samplist[st->
+				acc_bufsample_cnt]->xyz[1] = y;
+			st->inv_acc_samplist[st->
+				acc_bufsample_cnt]->xyz[2] = z;
+			st->inv_acc_samplist[st->
+				acc_bufsample_cnt]->tsec =
+				ktime_to_timespec(st
+						->timestamp).tv_sec;
+			st->inv_acc_samplist[st->
+				acc_bufsample_cnt]->tnsec =
+				ktime_to_timespec(st
+						->timestamp).tv_nsec;
+			st->acc_bufsample_cnt++;
+		}
+	} else {
+		dev_info(st->dev, "End of ACC buffering %d\n",
+					st->acc_bufsample_cnt);
+		st->acc_buffer_inv_samples = false;
+	}
+}
+static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t,
+						s16 x, s16 y, s16 z)
+{
+
+	if (false == st->gyro_buffer_inv_samples)
+		return;
+	st->timestamp.tv64 = t;
+	if (ktime_to_timespec(st->timestamp).tv_sec
+			<  st->max_buffer_time) {
+		if (st->gyro_bufsample_cnt < INV_GYRO_MAXSAMPLE) {
+			st->inv_gyro_samplist[st->
+				gyro_bufsample_cnt]->xyz[0] = x;
+			st->inv_gyro_samplist[st->
+				gyro_bufsample_cnt]->xyz[1] = y;
+			st->inv_gyro_samplist[st->
+				gyro_bufsample_cnt]->xyz[2] = z;
+			st->inv_gyro_samplist[st->
+				gyro_bufsample_cnt]->tsec =
+				ktime_to_timespec(st->
+						timestamp).tv_sec;
+			st->inv_gyro_samplist[st->
+				gyro_bufsample_cnt]->tnsec =
+				ktime_to_timespec(st->
+						timestamp).tv_nsec;
+			st->gyro_bufsample_cnt++;
+		}
+	} else {
+		dev_info(st->dev, "End of GYRO buffering %d\n",
+					st->gyro_bufsample_cnt);
+		st->gyro_buffer_inv_samples = false;
+	}
+}
+#else
+static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t,
+						s16 x, s16 y, s16 z)
+{
+}
+static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t,
+						s16 x, s16 y, s16 z)
+{
+}
+#endif
 
 int inv_push_special_8bytes_buffer(struct inv_mpu_state *st,
 				   u16 hdr, u64 t, s16 *d)
@@ -309,6 +383,7 @@
 	memcpy(&buf[2], &d[0], sizeof(d[0]));
 	for (j = 0; j < 2; j++)
 		memcpy(&buf[4 + j * 2], &d[j + 1], sizeof(d[j]));
+	store_gyro_boot_sample(st, t, d[0], d[1], d[2]);
 	iio_push_to_buffers(indio_dev, buf);
 	inv_push_timestamp(indio_dev, t);
 
@@ -399,7 +474,7 @@
 				for (j = 0; j < 2; j++)
 					memcpy(&buf[4 + j * 2], &d[j + 1],
 					       sizeof(d[j]));
-
+				store_acc_boot_sample(st, t, d[0], d[1], d[2]);
 				iio_push_to_buffers(indio_dev, buf);
 				inv_push_timestamp(indio_dev, t);
 				st->sensor_l[ii].counter = 0;
diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu/inv_mpu_spi.c
index fb91678..5199e62 100644
--- a/drivers/iio/imu/inv_mpu/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu/inv_mpu_spi.c
@@ -177,7 +177,7 @@
 	&& !defined(CONFIG_INV_MPU_IIO_IAM20680)
 	st->i2c_dis = BIT_I2C_IF_DIS;
 #endif
-	st->bus_type = BUS_SPI;
+	st->bus_type = BUS_IIO_SPI;
 	spi_set_drvdata(spi, indio_dev);
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->name = id->name;
diff --git a/drivers/iio/imu/st_asm330lhh/Kconfig b/drivers/iio/imu/st_asm330lhh/Kconfig
index 092cc48..ebdba32 100644
--- a/drivers/iio/imu/st_asm330lhh/Kconfig
+++ b/drivers/iio/imu/st_asm330lhh/Kconfig
@@ -21,3 +21,9 @@
 	tristate
 	depends on IIO_ST_ASM330LHH
 
+config ENABLE_ASM_ACC_GYRO_BUFFERING
+        bool "Enable accel & gyro  boot time sensor sample buffering"
+        depends on IIO_ST_ASM330LHH
+        help
+         Say Y here if you want to buffer boot time sensor
+         samples for ASM330 accelerometer and gyroscope
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
index 52b293f..9605ab2 100644
--- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
@@ -13,6 +13,9 @@
 
 #include <linux/device.h>
 #include <linux/iio/iio.h>
+#include <linux/input.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
 
 #define ST_ASM330LHH_REVISION		"2.0.1"
 #define ST_ASM330LHH_PATCH		"1"
@@ -82,6 +85,16 @@
 #define ST_ASM330LHH_RX_MAX_LENGTH	8
 #define ST_ASM330LHH_TX_MAX_LENGTH	8
 
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+#define ASM_MAXSAMPLE        4000
+#define G_MAX                    23920640
+struct asm_sample {
+	int xyz[3];
+	unsigned int tsec;
+	unsigned long long tnsec;
+};
+#endif
+
 struct st_asm330lhh_transfer_buffer {
 	u8 rx_buf[ST_ASM330LHH_RX_MAX_LENGTH];
 	u8 tx_buf[ST_ASM330LHH_TX_MAX_LENGTH] ____cacheline_aligned;
@@ -165,6 +178,17 @@
 	u16 watermark;
 	u8 batch_mask;
 	u8 batch_addr;
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+	bool read_boot_sample;
+	int bufsample_cnt;
+	bool buffer_asm_samples;
+	struct kmem_cache *asm_cachepool;
+	struct asm_sample *asm_samplist[ASM_MAXSAMPLE];
+	ktime_t timestamp;
+	int max_buffer_time;
+	struct input_dev *buf_dev;
+	int report_evt_cnt;
+#endif
 };
 
 /**
@@ -235,4 +259,9 @@
 int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw,
 			       enum st_asm330lhh_fifo_mode fifo_mode);
 int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw);
+int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
+					u16 watermark);
+int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable);
+int asm330_check_acc_gyro_early_buff_enable_flag(
+		struct st_asm330lhh_sensor *sensor);
 #endif /* ST_ASM330LHH_H */
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
index af8c5ba..734d735 100644
--- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
@@ -121,7 +121,7 @@
 	return odr;
 }
 
-static int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
+int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
 					 u16 watermark)
 {
 	u16 fifo_watermark = ST_ASM330LHH_MAX_FIFO_DEPTH, cur_watermark = 0;
@@ -190,11 +190,66 @@
 
 	return iio_dev;
 }
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+int asm330_check_acc_gyro_early_buff_enable_flag(
+		struct st_asm330lhh_sensor *sensor)
+{
+	if (sensor->buffer_asm_samples == true)
+		return 1;
+	else
+		return 0;
+}
+#else
+int asm330_check_acc_gyro_early_buff_enable_flag(
+		struct st_asm330lhh_sensor *sensor)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor,
+					u8 *iio_buf, s64 tsample)
+{
+	int x, y, z;
+
+	if (false == sensor->buffer_asm_samples)
+		return;
+
+	sensor->timestamp = (ktime_t)tsample;
+	x = iio_buf[1]<<8|iio_buf[0];
+	y = iio_buf[3]<<8|iio_buf[2];
+	z = iio_buf[5]<<8|iio_buf[4];
+
+	if (ktime_to_timespec(sensor->timestamp).tv_sec
+			<  sensor->max_buffer_time) {
+		if (sensor->bufsample_cnt < ASM_MAXSAMPLE) {
+			sensor->asm_samplist[sensor->bufsample_cnt]->xyz[0] = x;
+			sensor->asm_samplist[sensor->bufsample_cnt]->xyz[1] = y;
+			sensor->asm_samplist[sensor->bufsample_cnt]->xyz[2] = z;
+			sensor->asm_samplist[sensor->bufsample_cnt]->tsec =
+				ktime_to_timespec(sensor->timestamp).tv_sec;
+			sensor->asm_samplist[sensor->bufsample_cnt]->tnsec =
+				ktime_to_timespec(sensor->timestamp).tv_nsec;
+			sensor->bufsample_cnt++;
+		}
+	} else {
+		dev_info(sensor->hw->dev, "End of sensor %d buffering %d\n",
+				sensor->id, sensor->bufsample_cnt);
+		sensor->buffer_asm_samples = false;
+	}
+}
+#else
+static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor,
+					u8 *iio_buf, s64 tsample)
+{
+}
+#endif
 
 static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw)
 {
 	u8 iio_buf[ALIGN(ST_ASM330LHH_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)];
-	u8 buf[6 * ST_ASM330LHH_FIFO_SAMPLE_SIZE], tag, *ptr;
+	u8 buf[30 * ST_ASM330LHH_FIFO_SAMPLE_SIZE], tag, *ptr;
 	s64 ts_delta_hw_ts = 0, ts_irq;
 	s64 ts_delta_offs;
 	int i, err, read_len, word_len, fifo_len;
@@ -278,6 +333,8 @@
 					iio_push_to_buffers_with_timestamp(iio_dev,
 									   iio_buf,
 									   hw->tsample);
+					store_acc_gyro_boot_sample(sensor,
+							iio_buf, hw->tsample);
 				}
 			}
 			read_len += word_len;
@@ -316,6 +373,9 @@
 	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
 	int err, val;
 
+	if (asm330_check_acc_gyro_early_buff_enable_flag(sensor))
+		return -EBUSY;
+
 	mutex_lock(&iio_dev->mlock);
 	if (iio_buffer_enabled(iio_dev)) {
 		err = -EBUSY;
@@ -381,7 +441,7 @@
 	return err;
 }
 
-static int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable)
+int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable)
 {
 	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
 	struct st_asm330lhh_hw *hw = sensor->hw;
@@ -443,12 +503,22 @@
 
 static int st_asm330lhh_buffer_preenable(struct iio_dev *iio_dev)
 {
-	return st_asm330lhh_update_fifo(iio_dev, true);
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+
+	if (asm330_check_acc_gyro_early_buff_enable_flag(sensor))
+		return 0;
+	else
+		return st_asm330lhh_update_fifo(iio_dev, true);
 }
 
 static int st_asm330lhh_buffer_postdisable(struct iio_dev *iio_dev)
 {
-	return st_asm330lhh_update_fifo(iio_dev, false);
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+
+	if (asm330_check_acc_gyro_early_buff_enable_flag(sensor))
+		return 0;
+	else
+		return st_asm330lhh_update_fifo(iio_dev, false);
 }
 
 static const struct iio_buffer_setup_ops st_asm330lhh_buffer_ops = {
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
index 9d9ee20..21f1b8d3 100644
--- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
@@ -324,7 +324,7 @@
 				     u8 addr, int *val)
 {
 	int err, delay;
-	__le16 data;
+	__le16 data = 0;
 
 	if (sensor->id == ST_ASM330LHH_ID_TEMP) {
 		u8 status;
@@ -432,6 +432,9 @@
 	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
 	int err;
 
+	if (asm330_check_acc_gyro_early_buff_enable_flag(sensor))
+		return 0;
+
 	mutex_lock(&iio_dev->mlock);
 
 	switch (mask) {
@@ -494,10 +497,129 @@
 
 	return len;
 }
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+static int asm_read_bootsampl(struct st_asm330lhh_sensor  *sensor,
+		unsigned long enable_read)
+{
+	int i = 0;
+
+	if (enable_read) {
+		sensor->buffer_asm_samples = false;
+		for (i = 0; i < sensor->bufsample_cnt; i++) {
+			dev_dbg(sensor->hw->dev,
+				"sensor:%d count:%d x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n",
+				sensor->id, i, sensor->asm_samplist[i]->xyz[0],
+				sensor->asm_samplist[i]->xyz[1],
+				sensor->asm_samplist[i]->xyz[2],
+				sensor->asm_samplist[i]->tsec,
+				sensor->asm_samplist[i]->tnsec);
+			input_report_abs(sensor->buf_dev, ABS_X,
+					sensor->asm_samplist[i]->xyz[0]);
+			input_report_abs(sensor->buf_dev, ABS_Y,
+					sensor->asm_samplist[i]->xyz[1]);
+			input_report_abs(sensor->buf_dev, ABS_Z,
+					sensor->asm_samplist[i]->xyz[2]);
+			input_report_abs(sensor->buf_dev, ABS_RX,
+					sensor->asm_samplist[i]->tsec);
+			input_report_abs(sensor->buf_dev, ABS_RY,
+					sensor->asm_samplist[i]->tnsec);
+			input_sync(sensor->buf_dev);
+		}
+	} else {
+		/* clean up */
+		if (sensor->bufsample_cnt != 0) {
+			for (i = 0; i < ASM_MAXSAMPLE; i++)
+				kmem_cache_free(sensor->asm_cachepool,
+					sensor->asm_samplist[i]);
+			kmem_cache_destroy(sensor->asm_cachepool);
+			sensor->bufsample_cnt = 0;
+		}
+
+	}
+	/*SYN_CONFIG indicates end of data*/
+	input_event(sensor->buf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF);
+	input_sync(sensor->buf_dev);
+	dev_dbg(sensor->hw->dev, "End of gyro samples bufsample_cnt=%d\n",
+			sensor->bufsample_cnt);
+	return 0;
+}
+static ssize_t read_gyro_boot_sample_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				sensor->read_boot_sample);
+}
+static ssize_t read_gyro_boot_sample_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int err;
+	struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+	unsigned long enable = 0;
+
+	err = kstrtoul(buf, 10, &enable);
+	if (err)
+		return err;
+	if (enable > 1) {
+		dev_err(sensor->hw->dev,
+				"Invalid value of input, input=%ld\n", enable);
+		return -EINVAL;
+	}
+	err = asm_read_bootsampl(sensor, enable);
+	if (err)
+		return err;
+	sensor->read_boot_sample = enable;
+	return count;
+
+}
+
+static ssize_t read_acc_boot_sample_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				sensor->read_boot_sample);
+}
+
+static ssize_t read_acc_boot_sample_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int err;
+	struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+
+	unsigned long enable = 0;
+
+	err = kstrtoul(buf, 10, &enable);
+	if (err)
+		return err;
+	if (enable > 1) {
+		dev_err(sensor->hw->dev,
+				"Invalid value of input, input=%ld\n", enable);
+		return -EINVAL;
+	}
+	err = asm_read_bootsampl(sensor, enable);
+	if (err)
+		return err;
+	sensor->read_boot_sample = enable;
+	return count;
+}
+#endif
 
 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_asm330lhh_sysfs_sampling_frequency_avail);
 static IIO_DEVICE_ATTR(in_accel_scale_available, 0444,
 		       st_asm330lhh_sysfs_scale_avail, NULL, 0);
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+static IIO_DEVICE_ATTR(read_acc_boot_sample, 0444,
+		read_acc_boot_sample_show, read_acc_boot_sample_store, 0);
+static IIO_DEVICE_ATTR(read_gyro_boot_sample, 0444,
+		read_gyro_boot_sample_show, read_gyro_boot_sample_store, 0);
+#endif
 static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444,
 		       st_asm330lhh_sysfs_scale_avail, NULL, 0);
 static IIO_DEVICE_ATTR(in_temp_scale_available, 0444,
@@ -510,6 +632,9 @@
 
 static struct attribute *st_asm330lhh_acc_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+	&iio_dev_attr_read_acc_boot_sample.dev_attr.attr,
+#endif
 	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
 	&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
 	&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
@@ -530,6 +655,9 @@
 
 static struct attribute *st_asm330lhh_gyro_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+	&iio_dev_attr_read_gyro_boot_sample.dev_attr.attr,
+#endif
 	&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
 	&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
 	&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
@@ -706,6 +834,195 @@
 
 	return iio_dev;
 }
+#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
+static void st_asm330lhh_enable_acc_gyro(struct st_asm330lhh_hw *hw)
+{
+	int i = 0;
+	struct st_asm330lhh_sensor *sensor;
+	int  acc_gain = ST_ASM330LHH_ACC_FS_2G_GAIN;
+	int  gyro_gain = ST_ASM330LHH_GYRO_FS_125_GAIN;
+	int  delay;
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+		sensor = iio_priv(hw->iio_devs[i]);
+		sensor->odr = 104;
+		sensor->watermark = 30;
+		delay = 1000000 / sensor->odr;
+
+		if (sensor->id == ST_ASM330LHH_ID_ACC) {
+			st_asm330lhh_set_full_scale(sensor, acc_gain);
+			usleep_range(delay, 2 * delay);
+			st_asm330lhh_set_odr(sensor, sensor->odr);
+			usleep_range(delay, 2 * delay);
+			st_asm330lhh_update_watermark(sensor,
+					sensor->watermark);
+			usleep_range(delay, 2 * delay);
+			st_asm330lhh_update_fifo(hw->iio_devs[i], true);
+			usleep_range(delay, 2 * delay);
+		} else if (sensor->id == ST_ASM330LHH_ID_GYRO) {
+			st_asm330lhh_set_full_scale(sensor, gyro_gain);
+			usleep_range(delay, 2 * delay);
+			st_asm330lhh_set_odr(sensor, sensor->odr);
+			usleep_range(delay, 2 * delay);
+			st_asm330lhh_update_watermark(sensor,
+					sensor->watermark);
+			usleep_range(delay, 2 * delay);
+			st_asm330lhh_update_fifo(hw->iio_devs[i], true);
+			usleep_range(delay, 2 * delay);
+		}
+	}
+}
+
+static int asm330_acc_gyro_early_buff_init(struct st_asm330lhh_hw *hw)
+{
+	int i = 0, err = 0;
+	struct st_asm330lhh_sensor *acc;
+	struct st_asm330lhh_sensor *gyro;
+
+	acc = iio_priv(hw->iio_devs[ST_ASM330LHH_ID_ACC]);
+	gyro = iio_priv(hw->iio_devs[ST_ASM330LHH_ID_GYRO]);
+
+	acc->bufsample_cnt = 0;
+	gyro->bufsample_cnt = 0;
+	acc->report_evt_cnt = 5;
+	gyro->report_evt_cnt = 5;
+	acc->max_buffer_time = 40;
+	gyro->max_buffer_time = 40;
+
+	acc->asm_cachepool = kmem_cache_create("acc_sensor_sample",
+			sizeof(struct asm_sample),
+			0,
+			SLAB_HWCACHE_ALIGN, NULL);
+	if (!acc->asm_cachepool) {
+		dev_err(hw->dev,
+				"asm_acc_cachepool cache create failed\n");
+		err = -ENOMEM;
+		return 0;
+	}
+
+	for (i = 0; i < ASM_MAXSAMPLE; i++) {
+		acc->asm_samplist[i] =
+			kmem_cache_alloc(acc->asm_cachepool,
+					GFP_KERNEL);
+		if (!acc->asm_samplist[i]) {
+			err = -ENOMEM;
+			goto clean_exit1;
+		}
+	}
+
+	gyro->asm_cachepool = kmem_cache_create("gyro_sensor_sample"
+			, sizeof(struct asm_sample), 0,
+			SLAB_HWCACHE_ALIGN, NULL);
+	if (!gyro->asm_cachepool) {
+		dev_err(hw->dev,
+				"asm_gyro_cachepool cache create failed\n");
+		err = -ENOMEM;
+		goto clean_exit1;
+	}
+
+	for (i = 0; i < ASM_MAXSAMPLE; i++) {
+		gyro->asm_samplist[i] =
+			kmem_cache_alloc(gyro->asm_cachepool,
+					GFP_KERNEL);
+		if (!gyro->asm_samplist[i]) {
+			err = -ENOMEM;
+			goto clean_exit2;
+		}
+	}
+
+	acc->buf_dev = input_allocate_device();
+	if (!acc->buf_dev) {
+		err = -ENOMEM;
+		dev_err(hw->dev, "input device allocation failed\n");
+		goto clean_exit2;
+	}
+	acc->buf_dev->name = "asm_accbuf";
+	acc->buf_dev->id.bustype = BUS_I2C;
+	input_set_events_per_packet(acc->buf_dev,
+			acc->report_evt_cnt * ASM_MAXSAMPLE);
+	set_bit(EV_ABS, acc->buf_dev->evbit);
+	input_set_abs_params(acc->buf_dev, ABS_X,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(acc->buf_dev, ABS_Y,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(acc->buf_dev, ABS_Z,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(acc->buf_dev, ABS_RX,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(acc->buf_dev, ABS_RY,
+			-G_MAX, G_MAX, 0, 0);
+	err = input_register_device(acc->buf_dev);
+	if (err) {
+		dev_err(hw->dev,
+				"unable to register input device %s\n",
+				acc->buf_dev->name);
+		goto clean_exit3;
+	}
+
+	gyro->buf_dev = input_allocate_device();
+	if (!gyro->buf_dev) {
+		err = -ENOMEM;
+		dev_err(hw->dev, "input device allocation failed\n");
+		goto clean_exit4;
+	}
+	gyro->buf_dev->name = "asm_gyrobuf";
+	gyro->buf_dev->id.bustype = BUS_I2C;
+	input_set_events_per_packet(gyro->buf_dev,
+			gyro->report_evt_cnt * ASM_MAXSAMPLE);
+	set_bit(EV_ABS, gyro->buf_dev->evbit);
+	input_set_abs_params(gyro->buf_dev, ABS_X,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(gyro->buf_dev, ABS_Y,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(gyro->buf_dev, ABS_Z,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(gyro->buf_dev, ABS_RX,
+			-G_MAX, G_MAX, 0, 0);
+	input_set_abs_params(gyro->buf_dev, ABS_RY,
+			-G_MAX, G_MAX, 0, 0);
+	err = input_register_device(gyro->buf_dev);
+	if (err) {
+		dev_err(hw->dev,
+				"unable to register input device %s\n",
+				gyro->buf_dev->name);
+		goto clean_exit5;
+	}
+
+	acc->buffer_asm_samples = true;
+	gyro->buffer_asm_samples = true;
+
+	return 1;
+clean_exit5:
+	input_free_device(gyro->buf_dev);
+clean_exit4:
+	input_unregister_device(acc->buf_dev);
+clean_exit3:
+	input_free_device(acc->buf_dev);
+clean_exit2:
+	for (i = 0; i < ASM_MAXSAMPLE; i++)
+		kmem_cache_free(gyro->asm_cachepool,
+				gyro->asm_samplist[i]);
+	kmem_cache_destroy(gyro->asm_cachepool);
+clean_exit1:
+	for (i = 0; i < ASM_MAXSAMPLE; i++)
+		kmem_cache_free(acc->asm_cachepool,
+				acc->asm_samplist[i]);
+	kmem_cache_destroy(acc->asm_cachepool);
+
+	return 0;
+}
+#else
+static void st_asm330lhh_enable_acc_gyro(struct st_asm330lhh_hw *hw)
+{
+}
+static int asm330_acc_gyro_early_buff_init(struct st_asm330lhh_hw *hw)
+{
+	return 1;
+}
+#endif
+
 
 int st_asm330lhh_probe(struct device *dev, int irq,
 		       const struct st_asm330lhh_transfer_function *tf_ops)
@@ -756,10 +1073,17 @@
 			return err;
 	}
 
+	err = asm330_acc_gyro_early_buff_init(hw);
+	if (!err)
+		return err;
+
+	st_asm330lhh_enable_acc_gyro(hw);
+
 	dev_info(hw->dev, "probe ok\n");
 
 	return 0;
 }
+
 EXPORT_SYMBOL(st_asm330lhh_probe);
 
 static int __maybe_unused st_asm330lhh_suspend(struct device *dev)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a836169..491f9d7 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -460,7 +460,7 @@
 	struct arm_smmu_smr		*smrs;
 	struct arm_smmu_s2cr		*s2crs;
 	struct mutex			stream_map_mutex;
-
+	struct mutex			iommu_group_mutex;
 	unsigned long			va_size;
 	unsigned long			ipa_size;
 	unsigned long			pa_size;
@@ -2308,6 +2308,7 @@
 	struct iommu_group *group;
 	int i, idx, ret;
 
+	mutex_lock(&smmu->iommu_group_mutex);
 	mutex_lock(&smmu->stream_map_mutex);
 	/* Figure out a viable stream map entry allocation */
 	for_each_cfg_sme(fwspec, i, idx) {
@@ -2316,12 +2317,12 @@
 
 		if (idx != INVALID_SMENDX) {
 			ret = -EEXIST;
-			goto out_err;
+			goto sme_err;
 		}
 
 		ret = arm_smmu_find_sme(smmu, sid, mask);
 		if (ret < 0)
-			goto out_err;
+			goto sme_err;
 
 		idx = ret;
 		if (smrs && smmu->s2crs[idx].count == 0) {
@@ -2332,13 +2333,14 @@
 		smmu->s2crs[idx].count++;
 		cfg->smendx[i] = (s16)idx;
 	}
+	mutex_unlock(&smmu->stream_map_mutex);
 
 	group = iommu_group_get_for_dev(dev);
 	if (!group)
 		group = ERR_PTR(-ENOMEM);
 	if (IS_ERR(group)) {
 		ret = PTR_ERR(group);
-		goto out_err;
+		goto iommu_group_err;
 	}
 	iommu_group_put(group);
 
@@ -2346,15 +2348,19 @@
 	for_each_cfg_sme(fwspec, i, idx)
 		smmu->s2crs[idx].group = group;
 
-	mutex_unlock(&smmu->stream_map_mutex);
+	mutex_unlock(&smmu->iommu_group_mutex);
 	return 0;
 
-out_err:
+iommu_group_err:
+	mutex_lock(&smmu->stream_map_mutex);
+
+sme_err:
 	while (i--) {
 		arm_smmu_free_sme(smmu, cfg->smendx[i]);
 		cfg->smendx[i] = INVALID_SMENDX;
 	}
 	mutex_unlock(&smmu->stream_map_mutex);
+	mutex_unlock(&smmu->iommu_group_mutex);
 	return ret;
 }
 
@@ -4480,6 +4486,7 @@
 
 	smmu->num_mapping_groups = size;
 	mutex_init(&smmu->stream_map_mutex);
+	mutex_init(&smmu->iommu_group_mutex);
 
 	if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) {
 		smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L;
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 36c84df..30815df 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -369,8 +369,9 @@
 			unsigned int order = __fls(order_mask);
 
 			order_size = 1U << order;
-			page = alloc_pages((order_mask - order_size) ?
-					   gfp | __GFP_NORETRY : gfp, order);
+			page = alloc_pages(order ?
+					   (gfp | __GFP_NORETRY) &
+						~__GFP_RECLAIM : gfp, order);
 			if (!page)
 				continue;
 			if (!order)
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index 7e6287c..31482f9 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -546,12 +546,22 @@
 	av8l_fast_iopte *ptep;
 	unsigned long flags;
 	struct sg_mapping_iter miter;
-	unsigned int count = ALIGN(size, SZ_4K) >> PAGE_SHIFT;
+	size_t count = ALIGN(size, SZ_4K) >> PAGE_SHIFT;
 	int prot = IOMMU_READ | IOMMU_WRITE; /* TODO: extract from attrs */
 	bool is_coherent = is_dma_coherent(dev, attrs);
 	pgprot_t remap_prot = __get_dma_pgprot(attrs, PAGE_KERNEL, is_coherent);
 	struct page **pages;
 
+	/*
+	 * sg_alloc_table_from_pages accepts unsigned int value for count
+	 * so check count doesn't exceed UINT_MAX.
+	 */
+
+	if (count > UINT_MAX) {
+		dev_err(dev, "count: %zx exceeds UNIT_MAX\n", count);
+		return NULL;
+	}
+
 	prot = __get_iommu_pgprot(attrs, prot, is_coherent);
 
 	*handle = DMA_ERROR_CODE;
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 25b85ab..2dcac17 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, 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
@@ -1349,6 +1349,7 @@
 	struct iommu_debug_device *ddev = file->private_data;
 	struct device *dev = ddev->dev;
 	char c[2];
+	size_t buflen = sizeof(c);
 
 	if (*offset)
 		return 0;
@@ -1359,13 +1360,14 @@
 		c[0] = dev->archdata.mapping->domain ? '1' : '0';
 
 	c[1] = '\n';
-	if (copy_to_user(ubuf, &c, 2)) {
+	buflen = min(count, buflen);
+	if (copy_to_user(ubuf, &c, buflen)) {
 		pr_err("copy_to_user failed\n");
 		return -EFAULT;
 	}
 	*offset = 1;		/* non-zero means we're done */
 
-	return 2;
+	return buflen;
 }
 
 static const struct file_operations iommu_debug_dma_attach_fops = {
@@ -1393,7 +1395,7 @@
 	else
 		snprintf(buf, buf_len, "0x%pK\n", test_virt_addr);
 
-	buflen = strlen(buf);
+	buflen = min(count, strlen(buf)+1);
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1424,19 +1426,21 @@
 {
 	struct iommu_debug_device *ddev = file->private_data;
 	char c[2];
+	size_t buflen = sizeof(c);
 
 	if (*offset)
 		return 0;
 
 	c[0] = ddev->domain ? '1' : '0';
 	c[1] = '\n';
-	if (copy_to_user(ubuf, &c, 2)) {
+	buflen = min(count, buflen);
+	if (copy_to_user(ubuf, &c, buflen)) {
 		pr_err("copy_to_user failed\n");
 		return -EFAULT;
 	}
 	*offset = 1;		/* non-zero means we're done */
 
-	return 2;
+	return buflen;
 }
 
 static const struct file_operations iommu_debug_attach_fops = {
@@ -1514,7 +1518,7 @@
 	else
 		snprintf(buf, sizeof(buf), "pte=%016llx\n", pte);
 
-	buflen = strlen(buf);
+	buflen = min(count, strlen(buf)+1);
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1583,7 +1587,7 @@
 		snprintf(buf, 100, "%pa\n", &phys);
 	}
 
-	buflen = strlen(buf);
+	buflen = min(count, strlen(buf)+1);
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1636,7 +1640,7 @@
 	else
 		snprintf(buf, sizeof(buf), "%pa\n", &phys);
 
-	buflen = strlen(buf);
+	buflen = min(count, strlen(buf)+1);
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1869,7 +1873,7 @@
 	iova = ddev->iova;
 	snprintf(buf, sizeof(buf), "%pa\n", &iova);
 
-	buflen = strlen(buf);
+	buflen = min(count, strlen(buf)+1);
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err("Couldn't copy_to_user\n");
 		retval = -EFAULT;
diff --git a/drivers/leds/leds-qpnp-vibrator.c b/drivers/leds/leds-qpnp-vibrator.c
index 81f54f0..c428bfb 100644
--- a/drivers/leds/leds-qpnp-vibrator.c
+++ b/drivers/leds/leds-qpnp-vibrator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018-2019, 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
@@ -314,6 +314,13 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", !!chip->reg_en_ctl);
 }
 
+static ssize_t qpnp_vib_set_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+		/* At present, nothing to do with setting state */
+		return count;
+}
+
 static ssize_t qpnp_vib_get_duration(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -398,7 +405,7 @@
 }
 
 static struct device_attribute qpnp_vib_attrs[] = {
-	__ATTR(state, 0444, qpnp_vib_get_state, NULL),
+	__ATTR(state, 0664, qpnp_vib_get_state, qpnp_vib_set_state),
 	__ATTR(duration, 0664, qpnp_vib_get_duration, qpnp_vib_set_duration),
 	__ATTR(activate, 0664, qpnp_vib_get_activate, qpnp_vib_set_activate),
 };
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index 4ae2f0a..6d0e85a 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
@@ -509,8 +509,8 @@
 
 		if (!rc) {
 			CAM_DBG(CAM_CDM,
-				"write BL success for cnt=%d with tag=%d",
-				i, core->bl_tag);
+				"write BL success for cnt=%d with tag=%d total_cnt=%d",
+				i, core->bl_tag, req->data->cmd_arrary_count);
 
 			CAM_DBG(CAM_CDM, "Now commit the BL");
 			if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
@@ -550,35 +550,33 @@
 		cdm_hw = payload->hw;
 		core = (struct cam_cdm *)cdm_hw->core_info;
 
-		CAM_DBG(CAM_CDM, "IRQ status=%x", payload->irq_status);
+		CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status);
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
-			struct cam_cdm_bl_cb_request_entry *node;
+			struct cam_cdm_bl_cb_request_entry *node, *tnode;
 
-			CAM_DBG(CAM_CDM, "inline IRQ data=%x",
+			CAM_DBG(CAM_CDM, "inline IRQ data=0x%x",
 				payload->irq_data);
 			mutex_lock(&cdm_hw->hw_mutex);
-			node = cam_cdm_find_request_by_bl_tag(
-					payload->irq_data,
-					&core->bl_request_list);
-			if (node) {
+			list_for_each_entry_safe(node, tnode,
+					&core->bl_request_list, entry) {
 				if (node->request_type ==
 					CAM_HW_CDM_BL_CB_CLIENT) {
 					cam_cdm_notify_clients(cdm_hw,
 						CAM_CDM_CB_STATUS_BL_SUCCESS,
 						(void *)node);
 				} else if (node->request_type ==
-						CAM_HW_CDM_BL_CB_INTERNAL) {
+					CAM_HW_CDM_BL_CB_INTERNAL) {
 					CAM_ERR(CAM_CDM,
 						"Invalid node=%pK %d", node,
 						node->request_type);
 				}
 				list_del_init(&node->entry);
+				if (node->bl_tag == payload->irq_data) {
+					kfree(node);
+					break;
+				}
 				kfree(node);
-			} else {
-				CAM_ERR(CAM_CDM,
-					"Inval node, inline_irq st=%x data=%x",
-					payload->irq_status, payload->irq_data);
 			}
 			mutex_unlock(&cdm_hw->hw_mutex);
 		}
@@ -684,7 +682,7 @@
 			CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd");
 		work_status = queue_work(cdm_core->work_queue, &payload->work);
 		if (work_status == false) {
-			CAM_ERR(CAM_CDM, "Failed to queue work for irq=%x",
+			CAM_ERR(CAM_CDM, "Failed to queue work for irq=0x%x",
 				payload->irq_status);
 			kfree(payload);
 		}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index ae678ef..7308644 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1470,8 +1470,8 @@
 	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
 		complete(&ctx->config_done_complete);
 		CAM_DBG(CAM_ISP,
-			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
-			 handle, userdata, status, cookie);
+			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
+			 handle, userdata, status, cookie, ctx->ctx_index);
 	} else {
 		CAM_WARN(CAM_ISP,
 			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
@@ -1786,15 +1786,15 @@
 				msecs_to_jiffies(30));
 			if (rc <= 0) {
 				CAM_ERR(CAM_ISP,
-					"config done completion timeout for req_id=%llu rc = %d",
-					cfg->request_id, rc);
+					"config done completion timeout for req_id=%llu rc=%d ctx_index %d",
+					cfg->request_id, rc, ctx->ctx_index);
 				if (rc == 0)
 					rc = -ETIMEDOUT;
 			} else {
 				rc = 0;
 				CAM_DBG(CAM_ISP,
-					"config done Success for req_id=%llu",
-					cfg->request_id);
+					"config done Success for req_id=%llu ctx_index %d",
+					cfg->request_id, ctx->ctx_index);
 			}
 		}
 	} else {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
index 65c2327..dac985d 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
@@ -8,3 +8,4 @@
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_ir_led/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/Makefile
new file mode 100644
index 0000000..2444a34
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/Makefile
@@ -0,0 +1,10 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_ir_led_dev.o cam_ir_led_soc.o cam_ir_led_core.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_core.c
new file mode 100644
index 0000000..144578a
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_core.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2019, 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 "cam_ir_led_core.h"
+
+static int cam_ir_cut_on(struct cam_ir_led_ctrl *ictrl)
+{
+	if (!ictrl) {
+		CAM_ERR(CAM_IR_LED, "Ir_led control Null");
+		return -EINVAL;
+	}
+
+	gpio_direction_output(
+		ictrl->soc_info.gpio_data->cam_gpio_common_tbl[4].gpio, 0);
+	gpio_direction_input(
+		ictrl->soc_info.gpio_data->cam_gpio_common_tbl[3].gpio);
+
+	return 0;
+}
+
+static int cam_ir_cut_off(struct cam_ir_led_ctrl *ictrl)
+{
+	if (!ictrl) {
+		CAM_ERR(CAM_IR_LED, "Ir_led control Null");
+		return -EINVAL;
+	}
+
+	gpio_direction_output(
+		ictrl->soc_info.gpio_data->cam_gpio_common_tbl[0].gpio, 0);
+	gpio_direction_output(
+		ictrl->soc_info.gpio_data->cam_gpio_common_tbl[3].gpio, 0);
+	gpio_direction_input(
+		ictrl->soc_info.gpio_data->cam_gpio_common_tbl[4].gpio);
+
+	return 0;
+}
+
+static int cam_ir_led_set_intensity(struct cam_ir_led_ctrl *ictrl,
+			uint32_t ir_led_intensity)
+{
+	CAM_INFO(CAM_IR_LED, "ir_led_intensity=%d", ir_led_intensity);
+	switch (ir_led_intensity) {
+	case IRLED_INTENSITY_OFF:
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[0].gpio,
+			0);
+		break;
+
+	case IRLED_INTENSITY_LEVEL1:
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[0].gpio,
+			1);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[1].gpio,
+			1);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[2].gpio,
+			1);
+		break;
+
+	case IRLED_INTENSITY_LEVEL2:
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[0].gpio,
+			1);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[1].gpio,
+			0);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[2].gpio,
+			1);
+		break;
+	case IRLED_INTENSITY_LEVEL3:
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[0].gpio,
+			1);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[1].gpio,
+			1);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[2].gpio,
+			0);
+		break;
+	case IRLED_INTENSITY_LEVEL4:
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[0].gpio,
+			1);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[1].gpio,
+			0);
+		gpio_direction_output(
+			ictrl->soc_info.gpio_data->cam_gpio_common_tbl[2].gpio,
+			0);
+		break;
+	}
+	return 0;
+}
+
+int cam_ir_led_parser(struct cam_ir_led_ctrl *ictrl, void *arg)
+{
+	int rc = 0;
+	uint32_t  *cmd_buf =  NULL;
+	uintptr_t generic_ptr;
+	uint32_t  *offset = NULL;
+	size_t len_of_buffer;
+	struct cam_control *ioctl_ctrl = NULL;
+	struct cam_packet *csl_packet = NULL;
+	struct cam_config_dev_cmd config;
+	struct cam_cmd_buf_desc *cmd_desc = NULL;
+	struct cam_ir_led_set_on_off *cam_ir_led_info = NULL;
+
+	if (!ictrl || !arg) {
+		CAM_ERR(CAM_IR_LED, "ictrl/arg is NULL");
+		return -EINVAL;
+	}
+	/* getting CSL Packet */
+	ioctl_ctrl = (struct cam_control *)arg;
+
+	if (copy_from_user((&config), u64_to_user_ptr(ioctl_ctrl->handle),
+		sizeof(config))) {
+		CAM_ERR(CAM_IR_LED, "Copy cmd handle from user failed");
+		rc = -EFAULT;
+		return rc;
+	}
+
+	rc = cam_mem_get_cpu_buf(config.packet_handle,
+		(uintptr_t *)&generic_ptr, &len_of_buffer);
+	if (rc) {
+		CAM_ERR(CAM_IR_LED, "Failed in getting the buffer : %d", rc);
+		return rc;
+	}
+
+	if (config.offset > len_of_buffer) {
+		CAM_ERR(CAM_IR_LED,
+			"offset is out of bounds: offset: %lld len: %zu",
+			config.offset, len_of_buffer);
+		return -EINVAL;
+	}
+
+	/* Add offset to the ir_led csl header */
+	csl_packet = (struct cam_packet *)(uintptr_t)(generic_ptr +
+			config.offset);
+
+	offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+		csl_packet->cmd_buf_offset);
+	cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+	rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
+		(uintptr_t *)&generic_ptr, &len_of_buffer);
+	if (rc < 0) {
+		CAM_ERR(CAM_IR_LED, "Failed to get the command Buffer");
+		return -EINVAL;
+	}
+
+	cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+		cmd_desc->offset);
+	cam_ir_led_info = (struct cam_ir_led_set_on_off *)cmd_buf;
+
+	switch (csl_packet->header.op_code & 0xFFFFFF) {
+	case CAM_IR_LED_PACKET_OPCODE_ON:
+		CAM_INFO(CAM_IR_LED, ":CAM_IR_LED_PACKET_OPCODE_ON");
+		cam_ir_cut_on(ictrl);
+		cam_ir_led_set_intensity(ictrl,
+				cam_ir_led_info->ir_led_intensity);
+		break;
+	case CAM_IR_LED_PACKET_OPCODE_OFF:
+		CAM_INFO(CAM_IR_LED, "CAM_IR_LED_PACKET_OPCODE_OFF");
+		cam_ir_cut_off(ictrl);
+		break;
+	case CAM_PKT_NOP_OPCODE:
+		CAM_INFO(CAM_IR_LED, "CAM_IR_LED: CAM_PKT_NOP_OPCODE");
+		break;
+	default:
+		CAM_ERR(CAM_IR_LED, "Wrong Opcode : %d",
+			(csl_packet->header.op_code & 0xFFFFFF));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int cam_ir_led_stop_dev(struct cam_ir_led_ctrl *ictrl)
+{
+	int rc = 0;
+
+	rc = cam_ir_cut_off(ictrl);
+
+	return rc;
+}
+
+int cam_ir_led_release_dev(struct cam_ir_led_ctrl *ictrl)
+{
+	int rc = 0;
+
+	if (ictrl->device_hdl != -1) {
+		rc = cam_destroy_device_hdl(ictrl->device_hdl);
+		if (rc)
+			CAM_ERR(CAM_IR_LED,
+				"Failed in destroying device handle rc = %d",
+				rc);
+		ictrl->device_hdl = -1;
+	}
+
+	return rc;
+}
+
+void cam_ir_led_shutdown(struct cam_ir_led_ctrl *ictrl)
+{
+	int rc;
+
+	if (ictrl->ir_led_state == CAM_IR_LED_STATE_INIT)
+		return;
+
+	if ((ictrl->ir_led_state == CAM_IR_LED_STATE_CONFIG) ||
+		(ictrl->ir_led_state == CAM_IR_LED_STATE_START)) {
+		rc = cam_ir_led_stop_dev(ictrl);
+		if (rc)
+			CAM_ERR(CAM_IR_LED, "Stop Failed rc: %d", rc);
+	}
+
+	rc = cam_ir_led_release_dev(ictrl);
+	if (rc)
+		CAM_ERR(CAM_IR_LED, "Release failed rc: %d", rc);
+
+	ictrl->ir_led_state = CAM_IR_LED_STATE_INIT;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_core.h
new file mode 100644
index 0000000..6d50a40
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_core.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2019, 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 _CAM_IR_LED_CORE_H_
+#define _CAM_IR_LED_CORE_H_
+#include "cam_ir_led_dev.h"
+
+#define IRLED_INTENSITY_OFF    0
+#define IRLED_INTENSITY_LEVEL1 1
+#define IRLED_INTENSITY_LEVEL2 2
+#define IRLED_INTENSITY_LEVEL3 3
+#define IRLED_INTENSITY_LEVEL4 4
+#define IRLED_INTENSITY_MAX    5
+
+
+int cam_ir_led_parser(struct cam_ir_led_ctrl *fctrl, void *arg);
+void cam_ir_led_shutdown(struct cam_ir_led_ctrl *ir_led_ctrl);
+int cam_ir_led_stop_dev(struct cam_ir_led_ctrl *ir_led_ctrl);
+int cam_ir_led_release_dev(struct cam_ir_led_ctrl *fctrl);
+#endif /*_CAM_IR_LED_CORE_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_dev.c
new file mode 100644
index 0000000..3ba7745
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_dev.c
@@ -0,0 +1,384 @@
+/* Copyright (c) 2019, 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/module.h>
+#include "cam_ir_led_dev.h"
+#include "cam_ir_led_soc.h"
+#include "cam_ir_led_core.h"
+
+static int32_t cam_ir_led_driver_cmd(struct cam_ir_led_ctrl *ictrl,
+		void *arg, struct cam_ir_led_private_soc *soc_private)
+{
+	int rc = 0;
+	struct cam_control *cmd = (struct cam_control *)arg;
+
+		CAM_ERR(CAM_IR_LED, "%s, IN", __func__);
+	if (!ictrl || !arg) {
+		CAM_ERR(CAM_IR_LED, "ictrl/arg is NULL with arg:%pK ictrl%pK",
+			ictrl, arg);
+		return -EINVAL;
+	}
+
+	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+		CAM_ERR(CAM_IR_LED, "Invalid handle type: %d",
+			cmd->handle_type);
+		return -EINVAL;
+	}
+
+	mutex_lock(&(ictrl->ir_led_mutex));
+	switch (cmd->op_code) {
+	case CAM_ACQUIRE_DEV: {
+		struct cam_sensor_acquire_dev ir_led_acq_dev;
+		struct cam_create_dev_hdl dev_hdl;
+
+		CAM_DBG(CAM_IR_LED, "CAM_ACQUIRE_DEV");
+
+		if (ictrl->ir_led_state != CAM_IR_LED_STATE_INIT) {
+			CAM_ERR(CAM_IR_LED,
+				" Cannot apply Acquire dev: Prev state: %d",
+				ictrl->ir_led_state);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+
+		rc = copy_from_user(&ir_led_acq_dev,
+			u64_to_user_ptr(cmd->handle),
+			sizeof(ir_led_acq_dev));
+		if (rc) {
+			CAM_ERR(CAM_IR_LED, "Failed Copy from User rc=%d", rc);
+			goto release_mutex;
+		}
+
+		dev_hdl.priv = ictrl;
+
+		ir_led_acq_dev.device_handle =
+			cam_create_device_hdl(&dev_hdl);
+		ictrl->device_hdl =
+			ir_led_acq_dev.device_handle;
+
+		rc = copy_to_user(u64_to_user_ptr(cmd->handle), &ir_led_acq_dev,
+			sizeof(struct cam_sensor_acquire_dev));
+		if (rc) {
+			CAM_ERR(CAM_IR_LED, "Failed Copy to User rc=%d", rc);
+			rc = -EFAULT;
+			goto release_mutex;
+		}
+		ictrl->ir_led_state = CAM_IR_LED_STATE_ACQUIRE;
+		break;
+	}
+	case CAM_RELEASE_DEV: {
+		CAM_DBG(CAM_IR_LED, "CAM_RELEASE_DEV");
+		if ((ictrl->ir_led_state == CAM_IR_LED_STATE_INIT) ||
+			(ictrl->ir_led_state == CAM_IR_LED_STATE_START)) {
+			CAM_WARN(CAM_IR_LED,
+				" Cannot apply Release dev: Prev state:%d",
+				ictrl->ir_led_state);
+		}
+
+		if (ictrl->device_hdl == -1 &&
+			ictrl->ir_led_state == CAM_IR_LED_STATE_ACQUIRE) {
+			CAM_ERR(CAM_IR_LED,
+				" Invalid Handle: device hdl: %d",
+				ictrl->device_hdl);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+		rc = cam_ir_led_release_dev(ictrl);
+		if (rc)
+			CAM_ERR(CAM_IR_LED,
+				" Failed in destroying the device Handle rc= %d",
+				rc);
+		ictrl->ir_led_state = CAM_IR_LED_STATE_INIT;
+		break;
+	}
+	case CAM_QUERY_CAP: {
+		struct cam_ir_led_query_cap_info ir_led_cap = {0};
+
+		CAM_DBG(CAM_IR_LED, "CAM_QUERY_CAP");
+		ir_led_cap.slot_info = ictrl->soc_info.index;
+
+		if (copy_to_user(u64_to_user_ptr(cmd->handle), &ir_led_cap,
+			sizeof(struct cam_ir_led_query_cap_info))) {
+			CAM_ERR(CAM_IR_LED, " Failed Copy to User");
+			rc = -EFAULT;
+			goto release_mutex;
+		}
+		break;
+	}
+	case CAM_START_DEV: {
+		CAM_DBG(CAM_IR_LED, "CAM_START_DEV");
+		if ((ictrl->ir_led_state == CAM_IR_LED_STATE_INIT) ||
+			(ictrl->ir_led_state == CAM_IR_LED_STATE_START)) {
+			CAM_ERR(CAM_IR_LED,
+				"Cannot apply Start Dev: Prev state: %d",
+				ictrl->ir_led_state);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+		ictrl->ir_led_state = CAM_IR_LED_STATE_START;
+
+		break;
+	}
+	case CAM_STOP_DEV: {
+		CAM_DBG(CAM_IR_LED, "CAM_STOP_DEV ENTER");
+		if (ictrl->ir_led_state != CAM_IR_LED_STATE_START) {
+			CAM_WARN(CAM_IR_LED,
+				" Cannot apply Stop dev: Prev state is: %d",
+				ictrl->ir_led_state);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+		rc = cam_ir_led_stop_dev(ictrl);
+		if (rc) {
+			CAM_ERR(CAM_IR_LED, "Failed STOP_DEV: rc=%d\n", rc);
+			goto release_mutex;
+		}
+		ictrl->ir_led_state = CAM_IR_LED_STATE_ACQUIRE;
+		break;
+	}
+	case CAM_CONFIG_DEV: {
+		CAM_DBG(CAM_IR_LED, "CAM_CONFIG_DEV");
+		rc = cam_ir_led_parser(ictrl, arg);
+		if (rc) {
+			CAM_ERR(CAM_IR_LED, "Failed CONFIG_DEV: rc=%d\n", rc);
+			goto release_mutex;
+		}
+		break;
+	}
+	default:
+		CAM_ERR(CAM_IR_LED, "Invalid Opcode: %d", cmd->op_code);
+		rc = -EINVAL;
+	}
+
+release_mutex:
+	mutex_unlock(&(ictrl->ir_led_mutex));
+	return rc;
+}
+
+static const struct of_device_id cam_ir_led_dt_match[] = {
+	{.compatible = "qcom,camera-ir-led", .data = NULL},
+	{}
+};
+
+static long cam_ir_led_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	int rc = 0;
+	struct cam_ir_led_ctrl *ictrl = NULL;
+	struct cam_ir_led_private_soc *soc_private = NULL;
+
+	CAM_DBG(CAM_IR_LED, "Enter");
+
+	ictrl = v4l2_get_subdevdata(sd);
+	soc_private = ictrl->soc_info.soc_private;
+
+	switch (cmd) {
+	case VIDIOC_CAM_CONTROL: {
+		rc = cam_ir_led_driver_cmd(ictrl, arg,
+			soc_private);
+		break;
+	}
+	default:
+		CAM_ERR(CAM_IR_LED, " Invalid ioctl cmd type");
+		rc = -EINVAL;
+		break;
+	}
+
+	CAM_DBG(CAM_IR_LED, "Exit");
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+static long cam_ir_led_subdev_do_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, unsigned long arg)
+{
+	struct cam_control cmd_data;
+	int32_t rc = 0;
+
+	if (copy_from_user(&cmd_data, (void __user *)arg,
+		sizeof(cmd_data))) {
+		CAM_ERR(CAM_IR_LED,
+			" Failed to copy from user_ptr=%pK size=%zu",
+			(void __user *)arg, sizeof(cmd_data));
+		return -EFAULT;
+	}
+
+	switch (cmd) {
+	case VIDIOC_CAM_CONTROL: {
+		rc = cam_ir_led_subdev_ioctl(sd, cmd, &cmd_data);
+		if (rc)
+			CAM_ERR(CAM_IR_LED, "cam_ir_led_ioctl failed");
+		break;
+	}
+	default:
+		CAM_ERR(CAM_IR_LED, " Invalid compat ioctl cmd_type:%d",
+			cmd);
+		rc = -EINVAL;
+	}
+
+	if (!rc) {
+		if (copy_to_user((void __user *)arg, &cmd_data,
+			sizeof(cmd_data))) {
+			CAM_ERR(CAM_IR_LED,
+				" Failed to copy to user_ptr=%pK size=%zu",
+				(void __user *)arg, sizeof(cmd_data));
+			rc = -EFAULT;
+		}
+	}
+
+	return rc;
+}
+#endif
+
+static int cam_ir_led_platform_remove(struct platform_device *pdev)
+{
+	struct cam_ir_led_ctrl *ictrl;
+
+	ictrl = platform_get_drvdata(pdev);
+	if (!ictrl) {
+		CAM_ERR(CAM_IR_LED, " Ir_led device is NULL");
+		return 0;
+	}
+
+	devm_kfree(&pdev->dev, ictrl);
+
+	return 0;
+}
+
+static int cam_ir_led_subdev_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	struct cam_ir_led_ctrl *ir_led_ctrl =
+		v4l2_get_subdevdata(sd);
+
+	if (!ir_led_ctrl) {
+		CAM_ERR(CAM_IR_LED, " Ir_led ctrl ptr is NULL");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ir_led_ctrl->ir_led_mutex);
+	cam_ir_led_shutdown(ir_led_ctrl);
+	mutex_unlock(&ir_led_ctrl->ir_led_mutex);
+
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops cam_ir_led_subdev_core_ops = {
+	.ioctl = cam_ir_led_subdev_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl32 = cam_ir_led_subdev_do_ioctl
+#endif
+};
+
+static struct v4l2_subdev_ops cam_ir_led_subdev_ops = {
+	.core = &cam_ir_led_subdev_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops cam_ir_led_internal_ops = {
+	.close = cam_ir_led_subdev_close,
+};
+
+static int32_t cam_ir_led_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	struct cam_ir_led_ctrl *ir_led_ctrl = NULL;
+
+	CAM_ERR(CAM_IR_LED, "DBG:Enter");
+	if (!pdev->dev.of_node) {
+		CAM_ERR(CAM_IR_LED, "of_node NULL");
+		return -EINVAL;
+	}
+
+	ir_led_ctrl = kzalloc(sizeof(struct cam_ir_led_ctrl), GFP_KERNEL);
+	if (!ir_led_ctrl)
+		return -ENOMEM;
+
+	ir_led_ctrl->pdev = pdev;
+	ir_led_ctrl->soc_info.pdev = pdev;
+	ir_led_ctrl->soc_info.dev = &pdev->dev;
+	ir_led_ctrl->soc_info.dev_name = pdev->name;
+
+	rc = cam_ir_led_get_dt_data(ir_led_ctrl, &ir_led_ctrl->soc_info);
+	if (rc) {
+		CAM_ERR(CAM_IR_LED, "cam_ir_led_get_dt_data failed rc=%d", rc);
+		if (ir_led_ctrl->soc_info.soc_private != NULL) {
+			kfree(ir_led_ctrl->soc_info.soc_private);
+			ir_led_ctrl->soc_info.soc_private = NULL;
+		}
+		kfree(ir_led_ctrl);
+		ir_led_ctrl = NULL;
+		return -EINVAL;
+	}
+
+	ir_led_ctrl->v4l2_dev_str.internal_ops =
+		&cam_ir_led_internal_ops;
+	ir_led_ctrl->v4l2_dev_str.ops = &cam_ir_led_subdev_ops;
+	ir_led_ctrl->v4l2_dev_str.name = CAMX_IR_LED_DEV_NAME;
+	ir_led_ctrl->v4l2_dev_str.sd_flags =
+		V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+	ir_led_ctrl->v4l2_dev_str.ent_function = CAM_IRLED_DEVICE_TYPE;
+	ir_led_ctrl->v4l2_dev_str.token = ir_led_ctrl;
+
+	rc = cam_register_subdev(&(ir_led_ctrl->v4l2_dev_str));
+	if (rc) {
+		CAM_ERR(CAM_IR_LED, "Fail to create subdev with %d", rc);
+		goto free_resource;
+	}
+	ir_led_ctrl->device_hdl = -1;
+
+	platform_set_drvdata(pdev, ir_led_ctrl);
+	v4l2_set_subdevdata(&ir_led_ctrl->v4l2_dev_str.sd, ir_led_ctrl);
+
+	mutex_init(&(ir_led_ctrl->ir_led_mutex));
+
+	ir_led_ctrl->ir_led_state = CAM_IR_LED_STATE_INIT;
+	CAM_ERR(CAM_IR_LED, "DBG:Probe success");
+	return rc;
+free_resource:
+	kfree(ir_led_ctrl);
+	return rc;
+}
+
+MODULE_DEVICE_TABLE(of, cam_ir_led_dt_match);
+
+static struct platform_driver cam_ir_led_platform_driver = {
+	.probe = cam_ir_led_platform_probe,
+	.remove = cam_ir_led_platform_remove,
+	.driver = {
+		.name = "CAM-IR-LED-DRIVER",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_ir_led_dt_match,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init cam_ir_led_init_module(void)
+{
+	int32_t rc = 0;
+
+	rc = platform_driver_register(&cam_ir_led_platform_driver);
+	if (rc)
+		CAM_ERR(CAM_IR_LED, "platform probe for ir_led failed");
+
+	return rc;
+}
+
+static void __exit cam_ir_led_exit_module(void)
+{
+	platform_driver_unregister(&cam_ir_led_platform_driver);
+}
+
+module_init(cam_ir_led_init_module);
+module_exit(cam_ir_led_exit_module);
+MODULE_DESCRIPTION("CAM IR_LED");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_dev.h
new file mode 100644
index 0000000..b462adb
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_dev.h
@@ -0,0 +1,140 @@
+/* Copyright (c) 2019, 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 _CAM_IR_LED_DEV_H_
+#define _CAM_IR_LED_DEV_H_
+
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/cam_sensor.h>
+#include <media/cam_req_mgr.h>
+#include "cam_req_mgr_util.h"
+#include "cam_req_mgr_interface.h"
+#include "cam_subdev.h"
+#include "cam_mem_mgr.h"
+#include "cam_sensor_cmn_header.h"
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+#define CAMX_IR_LED_DEV_NAME "cam-ir-led-dev"
+
+#define CAM_IR_LED_PIPELINE_DELAY 1
+
+#define CAM_IR_LED_PACKET_OPCODE_OFF 0
+#define CAM_IR_LED_PACKET_OPCODE_ON  1
+
+enum cam_ir_led_switch_trigger_ops {
+	LED_SWITCH_OFF = 0,
+	LED_SWITCH_ON,
+};
+
+enum cam_ir_led_state {
+	CAM_IR_LED_STATE_INIT = 0,
+	CAM_IR_LED_STATE_ACQUIRE,
+	CAM_IR_LED_STATE_CONFIG,
+	CAM_IR_LED_STATE_START,
+};
+
+/**
+ * struct cam_ir_led_intf_params
+ * @device_hdl   : Device Handle
+ * @session_hdl  : Session Handle
+ * @link_hdl     : Link Handle
+ * @ops          : KMD operations
+ * @crm_cb       : Callback API pointers
+ */
+struct cam_ir_led_intf_params {
+	int32_t                     device_hdl;
+	int32_t                     session_hdl;
+	int32_t                     link_hdl;
+	struct cam_req_mgr_kmd_ops  ops;
+	struct cam_req_mgr_crm_cb  *crm_cb;
+};
+
+/**
+ * struct cam_ir_led_common_attr
+ * @is_settings_valid  : Notify the valid settings
+ * @request_id         : Request id provided by umd
+ * @count              : Number of led count
+ * @cmd_type           : Command buffer type
+ */
+struct cam_ir_led_common_attr {
+	bool      is_settings_valid;
+	uint64_t  request_id;
+	uint16_t  count;
+	uint8_t   cmd_type;
+};
+
+/**
+ * struct ir_led_init_packet
+ * @cmn_attr   : Provides common attributes
+ * @ir_led_type : Ir_led type(PMIC/I2C/GPIO)
+ */
+struct cam_ir_led_init_packet {
+	struct cam_ir_led_common_attr cmn_attr;
+	uint8_t                       ir_led_type;
+};
+
+/**
+ *  struct cam_ir_led_private_soc
+ * @switch_trigger_name : Switch trigger name
+ * @ir_led_trigger_name  : Ir_led trigger name array
+ * @ir_led_op_current    : Ir_led operational current
+ * @ir_led_max_current   : Max supported current for LED in ir_led mode
+ * @ir_led_max_duration  : Max turn on duration for LED in Ir_led mode
+ * @torch_trigger_name  : Torch trigger name array
+ * @torch_op_current    : Torch operational current
+ * @torch_max_current   : Max supported current for LED in torch mode
+ */
+
+struct cam_ir_led_private_soc {
+	const char   *switch_trigger_name;
+	const char   *ir_led_trigger_name;
+	uint32_t     ir_led_op_current;
+	uint32_t     ir_led_max_current;
+	uint32_t     ir_led_max_duration;
+	const char   *torch_trigger_name;
+	uint32_t     torch_op_current;
+	uint32_t     torch_max_current;
+};
+
+/**
+ *  struct cam_ir_led_ctrl
+ * @soc_info            : Soc related information
+ * @pdev                : Platform device
+ * @of_node             : Of Node ptr
+ * @v4l2_dev_str        : V4L2 device structure
+ * @ir_led_mutex        : Mutex for ir_led operations
+ * @ir_led_state        : Current ir_led state (LOW/OFF/ON/INIT)
+ * @device_hdl          : Device Handle
+ */
+struct cam_ir_led_ctrl {
+	struct cam_hw_soc_info  soc_info;
+	struct platform_device  *pdev;
+	struct device_node      *of_node;
+	struct cam_subdev       v4l2_dev_str;
+	struct mutex            ir_led_mutex;
+	enum   cam_ir_led_state ir_led_state;
+	int32_t                 device_hdl;
+};
+
+#endif /*_CAM_IR_LED_DEV_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_soc.c
new file mode 100644
index 0000000..65b5361
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_soc.c
@@ -0,0 +1,46 @@
+/* Copyright (c) 2019, 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/of.h>
+#include <linux/of_gpio.h>
+#include "cam_ir_led_soc.h"
+#include "cam_res_mgr_api.h"
+
+int cam_ir_led_get_dt_data(struct cam_ir_led_ctrl *ictrl,
+	struct cam_hw_soc_info *soc_info)
+{
+	int32_t rc = 0;
+
+	if (!ictrl) {
+		CAM_ERR(CAM_IR_LED, "NULL ir_led control structure");
+		return -EINVAL;
+	}
+
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc < 0) {
+		CAM_ERR(CAM_IR_LED, "get_dt_properties failed rc %d", rc);
+		return rc;
+	}
+
+	soc_info->soc_private =
+		kzalloc(sizeof(struct cam_ir_led_private_soc), GFP_KERNEL);
+	if (!soc_info->soc_private) {
+		rc = -ENOMEM;
+		goto release_soc_res;
+	}
+
+	return rc;
+
+release_soc_res:
+	cam_soc_util_release_platform_resource(soc_info);
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_soc.h
new file mode 100644
index 0000000..3a9139a
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ir_led/cam_ir_led_soc.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2019, 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 _CAM_IR_LED_SOC_H_
+#define _CAM_IR_LED_SOC_H_
+
+#include "cam_ir_led_dev.h"
+
+int cam_ir_led_get_dt_data(struct cam_ir_led_ctrl *fctrl,
+	struct cam_hw_soc_info *soc_info);
+
+#endif /*_CAM_IR_LED_SOC_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index c88e969..f91c077 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -455,6 +455,8 @@
 		s_ctrl->sensordata->subdev_id[SUB_MODULE_LED_FLASH];
 	query_cap->ois_slot_id =
 		s_ctrl->sensordata->subdev_id[SUB_MODULE_OIS];
+	query_cap->ir_led_slot_id =
+		s_ctrl->sensordata->subdev_id[SUB_MODULE_IR_LED];
 	query_cap->slot_info =
 		s_ctrl->soc_info.index;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
index e997419..4ca4d41 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -98,6 +98,21 @@
 	else
 		sensor_info->subdev_id[SUB_MODULE_CSIPHY] = val;
 
+	src_node = of_parse_phandle(of_node, "ir-led-src", 0);
+	if (!src_node) {
+		CAM_DBG(CAM_SENSOR, " src_node NULL");
+	} else {
+		rc = of_property_read_u32(src_node, "cell-index", &val);
+		CAM_DBG(CAM_SENSOR, "ir led cell index %d, rc %d", val, rc);
+		if (rc < 0) {
+			CAM_ERR(CAM_SENSOR, "failed %d", rc);
+			of_node_put(src_node);
+			return rc;
+		}
+		sensor_info->subdev_id[SUB_MODULE_IR_LED] = val;
+		of_node_put(src_node);
+	}
+
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index fddff38..1c9ee1f 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -132,6 +132,7 @@
 	SUB_MODULE_CSID,
 	SUB_MODULE_CSIPHY,
 	SUB_MODULE_OIS,
+	SUB_MODULE_IR_LED,
 	SUB_MODULE_EXT,
 	SUB_MODULE_MAX,
 };
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
index 9093517..81bc47b 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -36,6 +36,7 @@
 #define CAM_OIS        (1 << 20)
 #define CAM_RES        (1 << 21)
 #define CAM_MEM        (1 << 22)
+#define CAM_IR_LED     (1 << 23)
 
 /* CAM_IRQ_CTRL: For events in irq controller */
 #define CAM_IRQ_CTRL   (1 << 23)
diff --git a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c
index ee695d8..da407a7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c
@@ -70,18 +70,15 @@
 	.i2c_util = msm_sensor_cci_i2c_util,
 	.i2c_poll =  msm_camera_cci_i2c_poll,
 };
-#ifdef CONFIG_COMPAT
+
 static int32_t msm_laser_led_init(
 	struct msm_laser_led_ctrl_t *laser_led_ctrl,
-	struct msm_laser_led_cfg_data_t32 __user *laser_led_data)
-#else
-static int32_t msm_laser_led_init(
-	struct msm_laser_led_ctrl_t *laser_led_ctrl,
-	struct msm_laser_led_cfg_data_t __user *laser_led_data)
-#endif
+	void __user *argp)
 {
 	int32_t rc = -EFAULT;
 	struct msm_camera_cci_client *cci_client = NULL;
+	struct msm_laser_led_cfg_data_t __user *laser_led_data =
+		(struct msm_laser_led_cfg_data_t __user *) argp;
 
 	CDBG("Enter\n");
 
@@ -263,6 +260,53 @@
 
 	return rc;
 }
+
+static int32_t msm_laser_led_init32(
+	struct msm_laser_led_ctrl_t *laser_led_ctrl,
+	void __user *argp)
+{
+	int32_t rc = -EFAULT;
+	struct msm_laser_led_cfg_data_t32 __user *laser_led_data =
+		(struct msm_laser_led_cfg_data_t32 __user *) argp;
+	struct msm_camera_cci_client *cci_client = NULL;
+
+	CDBG("Enter\n");
+
+	if (laser_led_ctrl->laser_led_state == MSM_CAMERA_LASER_LED_INIT) {
+		pr_err("Invalid laser_led state = %d\n",
+				laser_led_ctrl->laser_led_state);
+		return 0;
+	}
+
+	rc = laser_led_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+			&laser_led_ctrl->i2c_client, MSM_CCI_INIT);
+	if (rc < 0)
+		pr_err("cci_init failed\n");
+
+	cci_client = laser_led_ctrl->i2c_client.cci_client;
+
+	if (copy_from_user(&(cci_client->sid),
+		&(laser_led_data->i2c_addr),
+		sizeof(uint16_t))) {
+		pr_err("%s:%d failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+	cci_client->sid = cci_client->sid >> 1;
+	cci_client->retries = 3;
+	cci_client->id_map = 0;
+
+	if (copy_from_user(&(cci_client->i2c_freq_mode),
+		&(laser_led_data->i2c_freq_mode),
+		sizeof(enum i2c_freq_mode_t))) {
+		pr_err("%s:%d failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	laser_led_ctrl->laser_led_state = MSM_CAMERA_LASER_LED_INIT;
+
+	CDBG("Exit\n");
+	return 0;
+}
 #endif
 
 static int32_t msm_laser_led_control(
@@ -381,7 +425,12 @@
 
 	switch (cfg_type) {
 	case CFG_LASER_LED_INIT:
-		rc = msm_laser_led_init(laser_led_ctrl, laser_led_data);
+#ifdef CONFIG_COMPAT
+		if (is_compat_task())
+			rc = msm_laser_led_init32(laser_led_ctrl, argp);
+		else
+#endif
+			rc = msm_laser_led_init(laser_led_ctrl, argp);
 		break;
 	case CFG_LASER_LED_CONTROL:
 #ifdef CONFIG_COMPAT
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index cdcfa96..82bc2b5 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -405,15 +405,10 @@
 
 	motion_vector_complexity = FP(integer_part, frac_part, 100);
 
-	dpb_write_compression_factor = !dpb_compression_enabled ? FP_ONE :
-		__compression_ratio(__lut(width, height, fps), opb_bpp);
-
-	dpb_write_compression_factor = d->use_dpb_read ?
-		dpb_read_compression_factor :
-		dpb_write_compression_factor;
+	dpb_write_compression_factor = dpb_read_compression_factor;
 
 	opb_compression_factor = !opb_compression_enabled ? FP_ONE :
-		__compression_ratio(__lut(width, height, fps), opb_bpp);
+				dpb_write_compression_factor;
 
 	llc_ref_read_l2_cache_enabled = llc_vpss_ds_line_buf_enabled = false;
 	if (d->use_sys_cache) {
@@ -425,7 +420,7 @@
 	lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
 		DIV_ROUND_UP(height, lcu_size);
 
-	bitrate = __lut(width, height, fps)->bitrate;
+	bitrate = (d->bitrate + 1000000 - 1) / 1000000;
 
 	bins_to_bit_factor = d->work_mode == VIDC_WORK_MODE_1 ?
 		FP_INT(0) : FP_INT(4);
@@ -479,7 +474,7 @@
 	if (llc_ref_read_l2_cache_enabled) {
 		row_cache_penalty = FP(1, 30, 100);
 		ddr.dpb_read = fp_div(ddr.dpb_read, row_cache_penalty);
-		llc.dpb_read = dpb_total - ddr.dpb_read;
+		llc.dpb_read = dpb_total - ddr.dpb_write - ddr.dpb_read;
 	}
 
 	opb_factor = dpb_bpp == 8 ? 8 : 4;
@@ -499,13 +494,14 @@
 	}
 	ddr.total = ddr.vsp_read + ddr.vsp_write +
 		ddr.collocated_read + ddr.collocated_write +
+		ddr.line_buffer_read + ddr.line_buffer_write +
 		ddr.opb_read + ddr.opb_write +
 		ddr.dpb_read + ddr.dpb_write;
 
 	qsmmu_bw_overhead_factor = FP(1, 3, 100);
 
 	ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
-	llc.total = llc.dpb_read + llc.opb_read;
+	llc.total = llc.dpb_read + llc.opb_read + ddr.total;
 
 	/* Dump all the variables for easier debugging */
 	if (debug) {
@@ -642,7 +638,8 @@
 	b_frames_enabled = d->b_frames_enabled;
 	width = max(d->input_width, BASELINE_DIMENSIONS.width);
 	height = max(d->input_height, BASELINE_DIMENSIONS.height);
-	bitrate = __lut(width, height, fps)->bitrate;
+	bitrate = d->bitrate > 0 ? d->bitrate / 1000000 :
+		__lut(width, height, fps)->bitrate;
 	lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
 		DIV_ROUND_UP(height, lcu_size);
 
@@ -686,10 +683,11 @@
 
 	input_compression_factor = FP(integer_part, frac_part, 100);
 
+	/* use input cr if it is valid (not 1), otherwise use lut */
 	original_compression_factor =
-		original_compression_enabled ? d->use_dpb_read ?
-			dpb_compression_factor : input_compression_factor :
-		FP_ONE;
+		!original_compression_enabled ? FP_ONE :
+		input_compression_factor != FP_ONE ? input_compression_factor :
+		__compression_ratio(__lut(width, height, fps), dpb_bpp);
 
 	ddr.vsp_read = fp_mult(fp_div(FP_INT(bitrate), FP_INT(8)),
 			bins_to_bit_factor);
@@ -743,7 +741,7 @@
 
 	llc_ref_y_read -= ref_y_read;
 
-	ref_cb_cr_read = fp_mult(ref_cb_cr_bw_factor, dpb_bw_for_1x);
+	ref_cb_cr_read = fp_mult(ref_cb_cr_bw_factor, dpb_bw_for_1x) / 2;
 
 	ref_cb_cr_read = fp_div(ref_cb_cr_read, dpb_compression_factor);
 
@@ -765,7 +763,7 @@
 
 	ddr.dpb_write = fp_mult(ddr.dpb_write, FP(1, 50, 100));
 
-	ddr.dpb_write = fp_div(ddr.dpb_write, input_compression_factor);
+	ddr.dpb_write = fp_div(ddr.dpb_write, dpb_compression_factor);
 
 	ref_overlap_bw_factor =
 		width <= vertical_tile_width ? FP_INT(0) : FP_INT(1);
@@ -787,7 +785,7 @@
 		ddr.original_read + ddr.original_write +
 		ddr.dpb_read + ddr.dpb_write;
 
-	llc.total = llc.dpb_read + llc.line_buffer;
+	llc.total = llc.dpb_read + llc.line_buffer + ddr.total;
 
 	qsmmu_bw_overhead_factor = FP(1, 3, 100);
 	ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 802e581..767ccaa 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -114,7 +114,9 @@
 {
 	struct recon_buf *binfo, *nextb;
 	struct vidc_input_cr_data *temp, *next;
-	u32 max_cr = 0, max_cf = 0, max_input_cr = 0;
+	u32 max_cr = MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO;
+	u32 max_cf = MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR;
+	u32 max_input_cr = MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO;
 	u32 min_cr = MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO;
 	u32 min_input_cr = MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO;
 	u32 min_cf = MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR;
@@ -184,13 +186,17 @@
 	hdev = core->device;
 
 	mutex_lock(&core->lock);
-	vote_data = core->vote_data;
+	list_for_each_entry(inst, &core->instances, list)
+		++vote_data_count;
+
+	vote_data = kcalloc(vote_data_count, sizeof(*vote_data),
+			GFP_TEMPORARY);
+	vote_data_count = 0;
 	if (!vote_data) {
-		dprintk(VIDC_PROF,
-			"Failed to get vote_data for inst %pK\n",
-				inst);
+		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
 		mutex_unlock(&core->lock);
-		return -EINVAL;
+		rc = -ENOMEM;
+		return rc;
 	}
 
 	list_for_each_entry(inst, &core->instances, list) {
@@ -260,6 +266,16 @@
 		else
 			vote_data[i].fps = inst->prop.fps;
 
+		if (inst->session_type == MSM_VIDC_ENCODER) {
+			vote_data[i].bitrate = inst->clk_data.bitrate;
+			/* scale bitrate if operating rate is larger than fps */
+			if (vote_data[i].fps > inst->prop.fps
+				&& inst->prop.fps) {
+				vote_data[i].bitrate = vote_data[i].bitrate /
+				inst->prop.fps * vote_data[i].fps;
+			}
+		}
+
 		vote_data[i].power_mode = 0;
 		if (!msm_vidc_clock_scaling || is_turbo ||
 			inst->clk_data.buffer_counter < DCVS_FTB_WINDOW)
@@ -293,6 +309,7 @@
 		rc = call_hfi_op(hdev, vote_bus, hdev->hfi_device_data,
 			vote_data, vote_data_count);
 
+	kfree(vote_data);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index f69b98e..c822776 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1404,7 +1404,7 @@
 	enum hal_video_codec codec;
 	enum hal_uncompressed_format color_formats[2];
 	int num_formats; /* 1 = DPB-OPB unified; 2 = split */
-	int input_height, input_width, fps;
+	int input_height, input_width, fps, bitrate;
 	int output_height, output_width;
 	int compression_ratio;
 	int complexity_factor;
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
index a80ae03..be3b992 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -1638,11 +1638,11 @@
 	list_for_each_entry(inst, &core->instances, list) {
 		mutex_lock(&inst->lock);
 		inst->state = MSM_VIDC_CORE_INVALID;
-		mutex_unlock(&inst->lock);
 		dprintk(VIDC_WARN,
 			"%s Send sys error for inst %pK\n", __func__, inst);
 		msm_vidc_queue_v4l2_event(inst,
 				V4L2_EVENT_MSM_VIDC_SYS_ERROR);
+		mutex_unlock(&inst->lock);
 	}
 	mutex_unlock(&core->lock);
 }
diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c
index 6ce3776..13175d0 100644
--- a/drivers/misc/hdcp_qseecom.c
+++ b/drivers/misc/hdcp_qseecom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -2037,6 +2037,30 @@
 	return hdcp1_supported;
 }
 
+void hdcp1_unload_app(void)
+{
+	int rc = 0;
+
+	if (!hdcp1_supported) {
+		pr_debug("hdcp1 is not supported\n");
+		return;
+	}
+
+	if (!hdcp1_handle) {
+		pr_debug("invalid hdcp1 handle\n");
+		return;
+	}
+
+	rc = qseecom_shutdown_app(&hdcp1_handle);
+	if (rc) {
+		pr_debug("qseecom_shutdown_app failed with ERR = %d\n", rc);
+		return;
+	}
+
+	hdcp1_handle = NULL;
+	pr_debug("hdcp1 app unloaded\n");
+}
+
 /* APIs exposed to all clients */
 int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
 {
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 45d3301..fbccd93 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,7 +1,7 @@
 /*
  * QTI Secure Execution Environment Communicator (QSEECOM) driver
  *
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, 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
@@ -146,6 +146,8 @@
 static DEFINE_MUTEX(qsee_bw_mutex);
 static DEFINE_MUTEX(app_access_lock);
 static DEFINE_MUTEX(clk_access_lock);
+static DEFINE_MUTEX(listener_access_lock);
+
 
 struct sglist_info {
 	uint32_t indexAndFlags;
@@ -185,15 +187,21 @@
 	size_t sb_length;
 	struct ion_handle *ihandle; /* Retrieve phy addr */
 	wait_queue_head_t          rcv_req_wq;
-	/* rcv_req_flag: -1: not ready; 0: ready and empty; 1: received req */
+	/* rcv_req_flag: 0: ready and empty; 1: received req */
 	int                        rcv_req_flag;
 	int                        send_resp_flag;
 	bool                       listener_in_use;
 	/* wq for thread blocked on this listener*/
 	wait_queue_head_t          listener_block_app_wq;
-	struct sglist_info sglistinfo_ptr[MAX_ION_FD];
-	uint32_t sglist_cnt;
-	int abort;
+	struct sglist_info         sglistinfo_ptr[MAX_ION_FD];
+	uint32_t                   sglist_cnt;
+	int                        abort;
+	bool                       unregister_pending;
+};
+
+struct qseecom_unregister_pending_list {
+	struct list_head		list;
+	struct qseecom_dev_handle	*data;
 };
 
 struct qseecom_registered_app_list {
@@ -241,7 +249,6 @@
 struct qseecom_control {
 	struct ion_client *ion_clnt;		/* Ion client */
 	struct list_head  registered_listener_list_head;
-	spinlock_t        registered_listener_list_lock;
 
 	struct list_head  registered_app_list_head;
 	spinlock_t        registered_app_list_lock;
@@ -288,6 +295,9 @@
 	atomic_t qseecom_state;
 	int is_apps_region_protected;
 	bool smcinvoke_support;
+
+	struct list_head  unregister_lsnr_pending_list_head;
+	wait_queue_head_t register_lsnr_pending_wq;
 };
 
 struct qseecom_sec_buf_fd_info {
@@ -316,6 +326,8 @@
 
 struct qseecom_listener_handle {
 	u32               id;
+	bool              unregister_pending;
+	bool              release_called;
 };
 
 static struct qseecom_control qseecom;
@@ -589,13 +601,11 @@
 			}
 			qseecom.smcinvoke_support = true;
 			smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID;
-			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
 			ret = scm_call2(smc_id, &desc);
-			if (ret) {
+			if (ret == -EIO) {
+				/* smcinvoke is not supported */
 				qseecom.smcinvoke_support = false;
 				smc_id = TZ_OS_REGISTER_LISTENER_ID;
-				__qseecom_reentrancy_check_if_no_app_blocked(
-					smc_id);
 				ret = scm_call2(smc_id, &desc);
 			}
 			break;
@@ -608,7 +618,6 @@
 			smc_id = TZ_OS_DEREGISTER_LISTENER_ID;
 			desc.arginfo = TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID;
 			desc.args[0] = req->listener_id;
-			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
 			ret = scm_call2(smc_id, &desc);
 			break;
 		}
@@ -1069,42 +1078,18 @@
 		return qseecom_scm_call2(svc_id, tz_cmd_id, cmd_buf, resp_buf);
 }
 
-static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
-		struct qseecom_register_listener_req *svc)
-{
-	struct qseecom_registered_listener_list *ptr;
-	int unique = 1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
-	list_for_each_entry(ptr, &qseecom.registered_listener_list_head, list) {
-		if (ptr->svc.listener_id == svc->listener_id) {
-			pr_err("Service id: %u is already registered\n",
-					ptr->svc.listener_id);
-			unique = 0;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
-	return unique;
-}
-
 static struct qseecom_registered_listener_list *__qseecom_find_svc(
 						int32_t listener_id)
 {
 	struct qseecom_registered_listener_list *entry = NULL;
-	unsigned long flags;
 
-	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
 	list_for_each_entry(entry,
 			&qseecom.registered_listener_list_head, list) {
 		if (entry->svc.listener_id == listener_id)
 			break;
 	}
-	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
-
 	if ((entry != NULL) && (entry->svc.listener_id != listener_id)) {
-		pr_err("Service id: %u is not found\n", listener_id);
+		pr_debug("Service id: %u is not found\n", listener_id);
 		return NULL;
 	}
 
@@ -1183,9 +1168,9 @@
 					void __user *argp)
 {
 	int ret = 0;
-	unsigned long flags;
 	struct qseecom_register_listener_req rcvd_lstnr;
 	struct qseecom_registered_listener_list *new_entry;
+	struct qseecom_registered_listener_list *ptr_svc;
 
 	ret = copy_from_user(&rcvd_lstnr, argp, sizeof(rcvd_lstnr));
 	if (ret) {
@@ -1197,18 +1182,37 @@
 		return -EFAULT;
 
 	data->listener.id = rcvd_lstnr.listener_id;
-	if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
-		pr_err("Service %d is not unique and failed to register\n",
+
+	ptr_svc = __qseecom_find_svc(rcvd_lstnr.listener_id);
+	if (ptr_svc) {
+		if (ptr_svc->unregister_pending == false) {
+			pr_err("Service %d is not unique\n",
 				rcvd_lstnr.listener_id);
 		data->released = true;
 		return -EBUSY;
+		} else {
+			/*wait until listener is unregistered*/
+			pr_debug("register %d has to wait\n",
+				rcvd_lstnr.listener_id);
+			mutex_unlock(&listener_access_lock);
+			ret = wait_event_freezable(
+				qseecom.register_lsnr_pending_wq,
+				list_empty(
+				&qseecom.unregister_lsnr_pending_list_head));
+			if (ret) {
+				pr_err("interrupted register_pending_wq %d\n",
+						rcvd_lstnr.listener_id);
+				mutex_lock(&listener_access_lock);
+				return -ERESTARTSYS;
+			}
+			mutex_lock(&listener_access_lock);
+		}
 	}
-
 	new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
 	if (!new_entry)
 		return -ENOMEM;
 	memcpy(&new_entry->svc, &rcvd_lstnr, sizeof(rcvd_lstnr));
-	new_entry->rcv_req_flag = -1;
+	new_entry->rcv_req_flag = 0;
 
 	new_entry->svc.listener_id = rcvd_lstnr.listener_id;
 	new_entry->sb_length = rcvd_lstnr.sb_size;
@@ -1224,45 +1228,20 @@
 	init_waitqueue_head(&new_entry->listener_block_app_wq);
 	new_entry->send_resp_flag = 0;
 	new_entry->listener_in_use = false;
-	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
 	list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head);
-	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
 
 	pr_warn("Service %d is registered\n", rcvd_lstnr.listener_id);
 	return ret;
 }
 
-static void __qseecom_listener_abort_all(int abort)
-{
-	struct qseecom_registered_listener_list *entry = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
-	list_for_each_entry(entry,
-			&qseecom.registered_listener_list_head, list) {
-		pr_debug("set abort %d for listener %d\n",
-				abort, entry->svc.listener_id);
-		entry->abort = abort;
-	}
-	if (abort)
-		wake_up_interruptible_all(&qseecom.send_resp_wq);
-	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
-}
-
-static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
+static int __qseecom_unregister_listener(struct qseecom_dev_handle *data,
+			struct qseecom_registered_listener_list *ptr_svc)
 {
 	int ret = 0;
 	struct qseecom_register_listener_ireq req;
-	struct qseecom_registered_listener_list *ptr_svc = NULL;
 	struct qseecom_command_scm_resp resp;
 	struct ion_handle *ihandle = NULL;		/* Retrieve phy addr */
 
-	ptr_svc = __qseecom_find_svc(data->listener.id);
-	if (!ptr_svc) {
-		pr_err("Unregiser invalid listener ID %d\n", data->listener.id);
-		return -ENODATA;
-	}
-
 	req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER;
 	req.listener_id = data->listener.id;
 	resp.result = QSEOS_RESULT_INCOMPLETE;
@@ -1272,6 +1251,8 @@
 	if (ret) {
 		pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
 				ret, data->listener.id);
+		if (ret == -EBUSY)
+			return ret;
 		goto exit;
 	}
 
@@ -1283,7 +1264,6 @@
 	}
 
 	data->abort = 1;
-	ptr_svc->abort = 1;
 	wake_up_all(&ptr_svc->rcv_req_wq);
 
 	while (atomic_read(&data->ioctl_count) > 1) {
@@ -1310,6 +1290,77 @@
 	return ret;
 }
 
+static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
+{
+	struct qseecom_registered_listener_list *ptr_svc = NULL;
+	struct qseecom_unregister_pending_list *entry = NULL;
+
+	ptr_svc = __qseecom_find_svc(data->listener.id);
+	if (!ptr_svc) {
+		pr_err("Unregiser invalid listener ID %d\n", data->listener.id);
+		return -ENODATA;
+	}
+	/* stop CA thread waiting for listener response */
+	ptr_svc->abort = 1;
+	wake_up_interruptible_all(&qseecom.send_resp_wq);
+
+	/* return directly if pending*/
+	if (ptr_svc->unregister_pending)
+		return 0;
+
+	/*add unregistration into pending list*/
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+	entry->data = data;
+	list_add_tail(&entry->list,
+		&qseecom.unregister_lsnr_pending_list_head);
+	ptr_svc->unregister_pending = true;
+	pr_debug("unregister %d pending\n", data->listener.id);
+	return 0;
+}
+
+static void __qseecom_processing_pending_lsnr_unregister(void)
+{
+	struct qseecom_unregister_pending_list *entry = NULL;
+	struct qseecom_registered_listener_list *ptr_svc = NULL;
+	struct list_head *pos;
+	int ret = 0;
+
+	mutex_lock(&listener_access_lock);
+	while (!list_empty(&qseecom.unregister_lsnr_pending_list_head)) {
+		pos = qseecom.unregister_lsnr_pending_list_head.next;
+		entry = list_entry(pos,
+				struct qseecom_unregister_pending_list, list);
+		if (entry && entry->data) {
+			pr_debug("process pending unregister %d\n",
+					entry->data->listener.id);
+			/* don't process if qseecom_release is not called*/
+			if (!entry->data->listener.release_called)
+				break;
+			ptr_svc = __qseecom_find_svc(
+						entry->data->listener.id);
+			if (ptr_svc) {
+				ret = __qseecom_unregister_listener(
+						entry->data, ptr_svc);
+				if (ret == -EBUSY) {
+					pr_debug("unregister %d pending again\n",
+						entry->data->listener.id);
+					mutex_unlock(&listener_access_lock);
+					return;
+				}
+			} else
+				pr_err("invalid listener %d\n",
+					entry->data->listener.id);
+			kzfree(entry->data);
+		}
+		list_del(pos);
+		kzfree(entry);
+	}
+	mutex_unlock(&listener_access_lock);
+	wake_up_interruptible(&qseecom.register_lsnr_pending_wq);
+}
+
 static int __qseecom_set_msm_bus_request(uint32_t mode)
 {
 	int ret = 0;
@@ -1644,19 +1695,12 @@
 	}
 }
 
-static int __is_listener_rcv_wq_not_ready(
-			struct qseecom_registered_listener_list *ptr_svc)
-{
-	return ptr_svc->rcv_req_flag == -1;
-}
-
 static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
 					struct qseecom_command_scm_resp *resp)
 {
 	int ret = 0;
 	int rc = 0;
 	uint32_t lstnr;
-	unsigned long flags;
 	struct qseecom_client_listener_data_irsp send_data_rsp = {0};
 	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit
 									= {0};
@@ -1667,30 +1711,23 @@
 	void *cmd_buf = NULL;
 	size_t cmd_len;
 	struct sglist_info *table = NULL;
-	bool not_ready = false;
 
+	qseecom.app_block_ref_cnt++;
 	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
 		/*
 		 * Wake up blocking lsitener service with the lstnr id
 		 */
-		spin_lock_irqsave(&qseecom.registered_listener_list_lock,
-					flags);
+		mutex_lock(&listener_access_lock);
 		list_for_each_entry(ptr_svc,
 				&qseecom.registered_listener_list_head, list) {
 			if (ptr_svc->svc.listener_id == lstnr) {
-				if (__is_listener_rcv_wq_not_ready(ptr_svc)) {
-					not_ready = true;
-					break;
-				}
 				ptr_svc->listener_in_use = true;
 				ptr_svc->rcv_req_flag = 1;
 				wake_up_interruptible(&ptr_svc->rcv_req_wq);
 				break;
 			}
 		}
-		spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
-				flags);
 
 		if (ptr_svc == NULL) {
 			pr_err("Listener Svc %d does not exist\n", lstnr);
@@ -1716,22 +1753,13 @@
 		}
 
 		if (ptr_svc->abort == 1) {
-			pr_err("Service %d abort %d\n",
+			pr_debug("Service %d abort %d\n",
 						lstnr, ptr_svc->abort);
 			rc = -ENODEV;
 			status = QSEOS_RESULT_FAILURE;
 			goto err_resp;
 		}
 
-		if (not_ready) {
-			pr_err("Service %d is not ready to receive request\n",
-					lstnr);
-			rc = -ENOENT;
-			status = QSEOS_RESULT_FAILURE;
-			goto err_resp;
-
-		}
-
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
 
 		/* initialize the new signal mask with all signals*/
@@ -1739,6 +1767,7 @@
 		/* block all signals */
 		sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
 
+		mutex_unlock(&listener_access_lock);
 		do {
 			/*
 			 * When reentrancy is not supported, check global
@@ -1759,7 +1788,7 @@
 				break;
 			}
 		} while (1);
-
+		mutex_lock(&listener_access_lock);
 		/* restore signal mask */
 		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
 		if (data->abort || ptr_svc->abort) {
@@ -1815,14 +1844,14 @@
 					ION_IOC_CLEAN_INV_CACHES);
 			if (ret) {
 				pr_err("cache operation failed %d\n", ret);
-				return ret;
+				goto exit;
 			}
 		}
 
 		if ((lstnr == RPMB_SERVICE) || (lstnr == SSD_SERVICE)) {
 			ret = __qseecom_enable_clk(CLK_QSEE);
 			if (ret)
-				return ret;
+				goto exit;
 		}
 
 		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
@@ -1836,7 +1865,7 @@
 				ret, data->client.app_id);
 			if ((lstnr == RPMB_SERVICE) || (lstnr == SSD_SERVICE))
 				__qseecom_disable_clk(CLK_QSEE);
-			return ret;
+			goto exit;
 		}
 		pr_debug("resp status %d, res= %d, app_id = %d, lstr = %d\n",
 			status, resp->result, data->client.app_id, lstnr);
@@ -1845,11 +1874,15 @@
 			pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
 				resp->result, data->client.app_id, lstnr);
 			ret = -EINVAL;
+			goto exit;
 		}
+exit:
+		mutex_unlock(&listener_access_lock);
 		if ((lstnr == RPMB_SERVICE) || (lstnr == SSD_SERVICE))
 			__qseecom_disable_clk(CLK_QSEE);
 
 	}
+	qseecom.app_block_ref_cnt--;
 	if (rc)
 		return rc;
 
@@ -1902,10 +1935,12 @@
 
 	do {
 		session_id = resp->resp_type;
+		mutex_lock(&listener_access_lock);
 		list_ptr = __qseecom_find_svc(resp->data);
 		if (!list_ptr) {
 			pr_err("Invalid listener ID %d\n", resp->data);
 			ret = -ENODATA;
+			mutex_unlock(&listener_access_lock);
 			goto exit;
 		}
 		ptr_app->blocked_on_listener_id = resp->data;
@@ -1921,11 +1956,13 @@
 		do {
 			qseecom.app_block_ref_cnt++;
 			ptr_app->app_blocked = true;
+			mutex_unlock(&listener_access_lock);
 			mutex_unlock(&app_access_lock);
 			wait_event_freezable(
 				list_ptr->listener_block_app_wq,
 				!list_ptr->listener_in_use);
 			mutex_lock(&app_access_lock);
+			mutex_lock(&listener_access_lock);
 			ptr_app->app_blocked = false;
 			qseecom.app_block_ref_cnt--;
 		}  while (list_ptr->listener_in_use);
@@ -1958,9 +1995,11 @@
 			if (ret) {
 				pr_err("unblock app %d or session %d fail\n",
 					data->client.app_id, session_id);
+				mutex_unlock(&listener_access_lock);
 				goto exit;
 			}
 		}
+		mutex_unlock(&listener_access_lock);
 		resp->result = continue_resp.result;
 		resp->resp_type = continue_resp.resp_type;
 		resp->data = continue_resp.data;
@@ -1982,7 +2021,6 @@
 	int ret = 0;
 	int rc = 0;
 	uint32_t lstnr;
-	unsigned long flags;
 	struct qseecom_client_listener_data_irsp send_data_rsp = {0};
 	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit
 									= {0};
@@ -1993,30 +2031,22 @@
 	void *cmd_buf = NULL;
 	size_t cmd_len;
 	struct sglist_info *table = NULL;
-	bool not_ready = false;
 
 	while (ret == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
 		/*
 		 * Wake up blocking lsitener service with the lstnr id
 		 */
-		spin_lock_irqsave(&qseecom.registered_listener_list_lock,
-					flags);
+		mutex_lock(&listener_access_lock);
 		list_for_each_entry(ptr_svc,
 				&qseecom.registered_listener_list_head, list) {
 			if (ptr_svc->svc.listener_id == lstnr) {
-				if (__is_listener_rcv_wq_not_ready(ptr_svc)) {
-					not_ready = true;
-					break;
-				}
 				ptr_svc->listener_in_use = true;
 				ptr_svc->rcv_req_flag = 1;
 				wake_up_interruptible(&ptr_svc->rcv_req_wq);
 				break;
 			}
 		}
-		spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
-				flags);
 
 		if (ptr_svc == NULL) {
 			pr_err("Listener Svc %d does not exist\n", lstnr);
@@ -2042,22 +2072,13 @@
 		}
 
 		if (ptr_svc->abort == 1) {
-			pr_err("Service %d abort %d\n",
+			pr_debug("Service %d abort %d\n",
 						lstnr, ptr_svc->abort);
 			rc = -ENODEV;
 			status = QSEOS_RESULT_FAILURE;
 			goto err_resp;
 		}
 
-		if (not_ready) {
-			pr_err("Service %d is not ready to receive request\n",
-					lstnr);
-			rc = -ENOENT;
-			status = QSEOS_RESULT_FAILURE;
-			goto err_resp;
-
-		}
-
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
 
 		/* initialize the new signal mask with all signals*/
@@ -2067,6 +2088,7 @@
 		sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
 
 		/* unlock mutex btw waking listener and sleep-wait */
+		mutex_unlock(&listener_access_lock);
 		mutex_unlock(&app_access_lock);
 		do {
 			if (!wait_event_freezable(qseecom.send_resp_wq,
@@ -2077,6 +2099,7 @@
 		} while (1);
 		/* lock mutex again after resp sent */
 		mutex_lock(&app_access_lock);
+		mutex_lock(&listener_access_lock);
 		ptr_svc->send_resp_flag = 0;
 		qseecom.send_resp_flag = 0;
 
@@ -2138,7 +2161,7 @@
 		if (lstnr == RPMB_SERVICE) {
 			ret = __qseecom_enable_clk(CLK_QSEE);
 			if (ret)
-				return ret;
+				goto exit;
 		}
 
 		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
@@ -2165,8 +2188,10 @@
 				ret = -EINVAL;
 				goto exit;
 			}
+			mutex_unlock(&listener_access_lock);
 			ret = __qseecom_process_reentrancy_blocked_on_listener(
 					resp, NULL, data);
+			mutex_lock(&listener_access_lock);
 			if (ret) {
 				pr_err("failed to process App(%d) %s blocked on listener %d\n",
 					data->client.app_id,
@@ -2183,6 +2208,7 @@
 			goto exit;
 		}
 exit:
+		mutex_unlock(&listener_access_lock);
 		if (lstnr == RPMB_SERVICE)
 			__qseecom_disable_clk(CLK_QSEE);
 
@@ -3271,6 +3297,7 @@
 		pr_err("cache operation failed %d\n", ret2);
 		return ret2;
 	}
+	__qseecom_processing_pending_lsnr_unregister();
 	return ret;
 }
 
@@ -3866,7 +3893,7 @@
 	int ret;
 
 	ret = (svc->rcv_req_flag == 1);
-	return ret || data->abort || svc->abort;
+	return ret || data->abort;
 }
 
 static int qseecom_receive_req(struct qseecom_dev_handle *data)
@@ -3874,14 +3901,14 @@
 	int ret = 0;
 	struct qseecom_registered_listener_list *this_lstnr;
 
+	mutex_lock(&listener_access_lock);
 	this_lstnr = __qseecom_find_svc(data->listener.id);
 	if (!this_lstnr) {
 		pr_err("Invalid listener ID\n");
+		mutex_unlock(&listener_access_lock);
 		return -ENODATA;
 	}
-
-	if (this_lstnr->rcv_req_flag == -1)
-		this_lstnr->rcv_req_flag = 0;
+	mutex_unlock(&listener_access_lock);
 
 	while (1) {
 		if (wait_event_freezable(this_lstnr->rcv_req_wq,
@@ -3890,16 +3917,17 @@
 			pr_warn("Interrupted: exiting Listener Service = %d\n",
 						(uint32_t)data->listener.id);
 			/* woken up for different reason */
-			this_lstnr->rcv_req_flag = -1;
 			return -ERESTARTSYS;
 		}
 
-		if (data->abort || this_lstnr->abort) {
+		if (data->abort) {
 			pr_err("Aborting Listener Service = %d\n",
 					(uint32_t)data->listener.id);
 			return -ENODEV;
 		}
+		mutex_lock(&listener_access_lock);
 		this_lstnr->rcv_req_flag = 0;
+		mutex_unlock(&listener_access_lock);
 		break;
 	}
 	return ret;
@@ -4486,6 +4514,8 @@
 	uint32_t fw_size, app_arch;
 	uint32_t app_id = 0;
 
+	__qseecom_processing_pending_lsnr_unregister();
+
 	if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
 		pr_err("Not allowed to be called in %d state\n",
 				atomic_read(&qseecom.qseecom_state));
@@ -4658,6 +4688,8 @@
 	unsigned long flags = 0;
 	bool found_handle = false;
 
+	__qseecom_processing_pending_lsnr_unregister();
+
 	if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
 		pr_err("Not allowed to be called in %d state\n",
 				atomic_read(&qseecom.qseecom_state));
@@ -4706,6 +4738,8 @@
 	struct qseecom_dev_handle *data;
 	bool perf_enabled = false;
 
+	__qseecom_processing_pending_lsnr_unregister();
+
 	if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
 		pr_err("Not allowed to be called in %d state\n",
 				atomic_read(&qseecom.qseecom_state));
@@ -7018,6 +7052,11 @@
 		pr_err("Aborting qseecom driver\n");
 		return -ENODEV;
 	}
+	if (cmd != QSEECOM_IOCTL_RECEIVE_REQ &&
+		cmd != QSEECOM_IOCTL_SEND_RESP_REQ &&
+		cmd != QSEECOM_IOCTL_SEND_MODFD_RESP &&
+		cmd != QSEECOM_IOCTL_SEND_MODFD_RESP_64)
+		__qseecom_processing_pending_lsnr_unregister();
 
 	switch (cmd) {
 	case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
@@ -7028,13 +7067,13 @@
 			break;
 		}
 		pr_debug("ioctl register_listener_req()\n");
-		mutex_lock(&app_access_lock);
+		mutex_lock(&listener_access_lock);
 		atomic_inc(&data->ioctl_count);
 		data->type = QSEECOM_LISTENER_SERVICE;
 		ret = qseecom_register_listener(data, argp);
 		atomic_dec(&data->ioctl_count);
 		wake_up_all(&data->abort_wq);
-		mutex_unlock(&app_access_lock);
+		mutex_unlock(&listener_access_lock);
 		if (ret)
 			pr_err("failed qseecom_register_listener: %d\n", ret);
 		break;
@@ -7060,14 +7099,12 @@
 			break;
 		}
 		pr_debug("ioctl unregister_listener_req()\n");
-		__qseecom_listener_abort_all(1);
-		mutex_lock(&app_access_lock);
+		mutex_lock(&listener_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_unregister_listener(data);
 		atomic_dec(&data->ioctl_count);
 		wake_up_all(&data->abort_wq);
-		mutex_unlock(&app_access_lock);
-		__qseecom_listener_abort_all(0);
+		mutex_unlock(&listener_access_lock);
 		if (ret)
 			pr_err("failed qseecom_unregister_listener: %d\n", ret);
 		break;
@@ -7222,6 +7259,7 @@
 			ret = -EINVAL;
 			break;
 		}
+		mutex_lock(&listener_access_lock);
 		atomic_inc(&data->ioctl_count);
 		if (!qseecom.qsee_reentrancy_support)
 			ret = qseecom_send_resp();
@@ -7229,6 +7267,7 @@
 			ret = qseecom_reentrancy_send_resp(data);
 		atomic_dec(&data->ioctl_count);
 		wake_up_all(&data->abort_wq);
+		mutex_unlock(&listener_access_lock);
 		if (ret)
 			pr_err("failed qseecom_send_resp: %d\n", ret);
 		break;
@@ -7564,6 +7603,7 @@
 			ret = -EINVAL;
 			break;
 		}
+		mutex_lock(&listener_access_lock);
 		atomic_inc(&data->ioctl_count);
 		if (cmd == QSEECOM_IOCTL_SEND_MODFD_RESP)
 			ret = qseecom_send_modfd_resp(data, argp);
@@ -7571,6 +7611,7 @@
 			ret = qseecom_send_modfd_resp_64(data, argp);
 		atomic_dec(&data->ioctl_count);
 		wake_up_all(&data->abort_wq);
+		mutex_unlock(&listener_access_lock);
 		if (ret)
 			pr_err("failed qseecom_send_mod_resp: %d\n", ret);
 		__qseecom_clean_data_sglistinfo(data);
@@ -7728,18 +7769,19 @@
 {
 	struct qseecom_dev_handle *data = file->private_data;
 	int ret = 0;
+	bool free_private_data = true;
 
 	if (data->released == false) {
 		pr_debug("data: released=false, type=%d, mode=%d, data=0x%pK\n",
 			data->type, data->mode, data);
 		switch (data->type) {
 		case QSEECOM_LISTENER_SERVICE:
-			pr_warn("release lsnr svc %d\n", data->listener.id);
-			__qseecom_listener_abort_all(1);
-			mutex_lock(&app_access_lock);
+			pr_debug("release lsnr svc %d\n", data->listener.id);
+			free_private_data = false;
+			mutex_lock(&listener_access_lock);
 			ret = qseecom_unregister_listener(data);
-			mutex_unlock(&app_access_lock);
-			__qseecom_listener_abort_all(0);
+			data->listener.release_called = true;
+			mutex_unlock(&listener_access_lock);
 			break;
 		case QSEECOM_CLIENT_APP:
 			mutex_lock(&app_access_lock);
@@ -7778,8 +7820,9 @@
 		if (data->perf_enabled == true)
 			qsee_disable_clock_vote(data, CLK_DFAB);
 	}
-	kfree(data);
 
+	if (free_private_data)
+		kfree(data);
 	return ret;
 }
 
@@ -8606,12 +8649,13 @@
 	}
 
 	INIT_LIST_HEAD(&qseecom.registered_listener_list_head);
-	spin_lock_init(&qseecom.registered_listener_list_lock);
 	INIT_LIST_HEAD(&qseecom.registered_app_list_head);
 	spin_lock_init(&qseecom.registered_app_list_lock);
+	INIT_LIST_HEAD(&qseecom.unregister_lsnr_pending_list_head);
 	INIT_LIST_HEAD(&qseecom.registered_kclient_list_head);
 	spin_lock_init(&qseecom.registered_kclient_list_lock);
 	init_waitqueue_head(&qseecom.send_resp_wq);
+	init_waitqueue_head(&qseecom.register_lsnr_pending_wq);
 	qseecom.send_resp_flag = 0;
 
 	qseecom.qsee_version = QSEEE_VERSION_00;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 04ac554..448aea0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1300,6 +1300,17 @@
 
 	mmc_get_card(card);
 
+	if (mmc_card_cmdq(card)) {
+		err = mmc_cmdq_halt(card->host, true);
+		if (err) {
+			pr_err("%s: halt failed while doing %s err (%d)\n",
+					mmc_hostname(card->host),
+					__func__, err);
+			mmc_put_card(card);
+			goto cmd_done;
+		}
+	}
+
 	for (i = 0; i < num_of_cmds && !ioc_err; i++)
 		ioc_err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
 
@@ -1307,6 +1318,12 @@
 	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
 		mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
 
+	if (mmc_card_cmdq(card)) {
+		if (mmc_cmdq_halt(card->host, false))
+			pr_err("%s: %s: cmdq unhalt failed\n",
+			       mmc_hostname(card->host), __func__);
+	}
+
 	mmc_put_card(card);
 
 	/* copy to user if data and response */
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index a4d35d9..765c1f5 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -684,7 +684,7 @@
 
 	cq_host->thist[cq_host->thist_idx].is_dcmd = is_dcmd;
 	memcpy(&cq_host->thist[cq_host->thist_idx++].task,
-		&task, cq_host->task_desc_len);
+		&task, sizeof(task));
 }
 
 static void cmdq_prep_dcmd_desc(struct mmc_host *mmc,
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 707190d..cf5b7a9 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -622,7 +622,9 @@
 	if ((regval & 0xFF) == 0xFF) {
 		phy_init_hw(phydev);
 		phydev->link = 0;
-		if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
+		if (phydev->drv->config_intr &&
+		    (phydev->irq == PHY_IGNORE_INTERRUPT ||
+		     phy_interrupt_is_valid(phydev)))
 			phydev->drv->config_intr(phydev);
 		return genphy_config_aneg(phydev);
 	}
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 751e911..6771f6a 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -1841,6 +1842,7 @@
 	{"RGF_MAC_MTRL_COUNTER_0", 0444, HOSTADDR(RGF_MAC_MTRL_COUNTER_0),
 		doff_io32},
 	{"RGF_USER_USAGE_1", 0444, HOSTADDR(RGF_USER_USAGE_1), doff_io32},
+	{"RGF_USER_USAGE_2", 0444, HOSTADDR(RGF_USER_USAGE_2), doff_io32},
 	{},
 };
 
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index d0fecd9..a1327be 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -41,6 +42,11 @@
 module_param(rx_large_buf, bool, 0444);
 MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no");
 
+static bool drop_if_ring_full;
+module_param(drop_if_ring_full, bool, 0444);
+MODULE_PARM_DESC(drop_if_ring_full,
+		 " drop Tx packets in case tx ring is full");
+
 static inline uint wil_rx_snaplen(void)
 {
 	return rx_align_2 ? 6 : 0;
@@ -323,14 +329,13 @@
 		return -ENOMEM;
 	}
 
-	d->mac.pn_15_0 = 0;
-	d->mac.pn_47_16 = 0;
+	memset(d, 0, sizeof(*d));
 	d->dma.d0 = RX_DMA_D0_CMD_DMA_RT | RX_DMA_D0_CMD_DMA_IT;
 	wil_desc_addr_set(&d->dma.addr, pa);
 	/* ip_length don't care */
 	/* b11 don't care */
 	/* error don't care */
-	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
+	/* BIT(0) of dma status should be 0 for HW_OWNED */
 	d->dma.length = cpu_to_le16(sz);
 	*_d = *d;
 	vring->ctx[i].skb = skb;
@@ -1918,6 +1923,10 @@
 		wil_dbg_txrx(wil, "check_stop=%d, stopped=%d",
 			     check_stop, wil->net_queue_stopped);
 
+	if (vring && drop_if_ring_full)
+		/* no need to stop/wake net queues */
+		return;
+
 	if (check_stop == wil->net_queue_stopped)
 		/* net queues already in desired state */
 		return;
@@ -2040,6 +2049,8 @@
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	case -ENOMEM:
+		if (drop_if_ring_full)
+			goto drop;
 		return NETDEV_TX_BUSY;
 	default:
 		break; /* goto drop; */
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 633e30f..4b781ca 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -162,6 +162,7 @@
 
 /* registers - FW addresses */
 #define RGF_USER_USAGE_1		(0x880004)
+#define RGF_USER_USAGE_2		(0x880008)
 #define RGF_USER_USAGE_6		(0x880018)
 	#define BIT_USER_OOB_MODE		BIT(31)
 	#define BIT_USER_OOB_R2_MODE		BIT(30)
diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c
index 8ed2630..be71d52 100644
--- a/drivers/net/wireless/cnss/cnss_sdio.c
+++ b/drivers/net/wireless/cnss/cnss_sdio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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,8 +46,9 @@
 
 #define WLAN_VREG_IO_MAX	1800000
 #define WLAN_VREG_IO_MIN	1800000
-#define WLAN_VREG_XTAL_MAX	1800000
-#define WLAN_VREG_XTAL_MIN	1800000
+#define WLAN_VREG_XTAL_MAX	3465000
+#define WLAN_VREG_XTAL_MIN	1620000
+#define WLAN_VREG_XTAL_TYP	1800000
 #define POWER_ON_DELAY		4
 
 /* Values for Dynamic Ramdump Collection*/
@@ -1244,6 +1245,8 @@
 {
 	int error;
 	struct device *dev = &cnss_pdata->pdev->dev;
+	u32 vdd_xtal_min;
+	u32 vdd_xtal_max;
 
 	if (of_get_property(
 		cnss_pdata->pdev->dev.of_node,
@@ -1283,9 +1286,32 @@
 			goto err_vdd_xtal_regulator;
 		}
 
+		if (!of_property_read_u32(cnss_pdata->pdev->dev.of_node,
+					  WLAN_VREG_XTAL_NAME "-min",
+					  &vdd_xtal_min)) {
+			if (vdd_xtal_min < WLAN_VREG_XTAL_MIN ||
+			    vdd_xtal_min > WLAN_VREG_XTAL_MAX)
+				vdd_xtal_min = WLAN_VREG_XTAL_TYP;
+		} else {
+			vdd_xtal_min = WLAN_VREG_XTAL_TYP;
+		}
+
+		if (!of_property_read_u32(cnss_pdata->pdev->dev.of_node,
+					  WLAN_VREG_XTAL_NAME "-max",
+					  &vdd_xtal_max)) {
+			if (vdd_xtal_max < WLAN_VREG_XTAL_MIN ||
+			    vdd_xtal_max > WLAN_VREG_XTAL_MAX)
+				vdd_xtal_max = WLAN_VREG_XTAL_TYP;
+		} else {
+			vdd_xtal_max = WLAN_VREG_XTAL_TYP;
+		}
+
+		if (vdd_xtal_min > vdd_xtal_max)
+			vdd_xtal_min = vdd_xtal_max;
+
 		error = regulator_set_voltage(
 			cnss_pdata->regulator.wlan_xtal,
-			WLAN_VREG_XTAL_MIN, WLAN_VREG_XTAL_MAX);
+			vdd_xtal_min, vdd_xtal_max);
 		if (error) {
 			dev_err(dev, "VDD-XTAL set failed error=%d\n", error);
 			goto err_vdd_xtal_regulator;
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
index bbf707b..14e9d36 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
@@ -2231,6 +2231,24 @@
 					   mem_cfg_mode),
 	},
 	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x1D,
+		.offset         = offsetof(struct wlfw_host_cap_req_msg_v01,
+					   cal_duration_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_2_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x1D,
+		.offset         = offsetof(struct wlfw_host_cap_req_msg_v01,
+					   cal_duration),
+	},
+	{
 		.data_type      = QMI_EOTI,
 		.is_array       = NO_ARRAY,
 		.tlv_type       = QMI_COMMON_TLV_TYPE,
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
index 00a873d..dc2f355 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
@@ -600,9 +600,11 @@
 	u32 mem_bucket;
 	u8 mem_cfg_mode_valid;
 	u8 mem_cfg_mode;
+	u8 cal_duration_valid;
+	u16 cal_duration;
 };
 
-#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
+#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 194
 extern struct elem_info wlfw_host_cap_req_msg_v01_ei[];
 
 struct wlfw_host_cap_resp_msg_v01 {
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 37df1bf..09e8d38 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -752,11 +752,7 @@
 		if (!event)
 			continue;
 
-		/*
-		 * Check if an attempt was made to free this event during
-		 * the CPU went offline.
-		 */
-		if (event->state == PERF_EVENT_STATE_ZOMBIE)
+		if (event->state != PERF_EVENT_STATE_ACTIVE)
 			continue;
 
 		switch (cmd) {
@@ -882,10 +878,8 @@
 	if (!pmu || !cpumask_test_cpu(cpu, &pmu->supported_cpus))
 		return 0;
 
-	data.cmd    = CPU_PM_EXIT;
-	cpu_pm_pmu_common(&data);
-	if (data.ret == NOTIFY_DONE)
-		return 0;
+	if (pmu->reset)
+		pmu->reset(pmu);
 
 	if (data.armpmu->pmu_state != ARM_PMU_STATE_OFF &&
 		data.armpmu->plat_device) {
@@ -911,8 +905,6 @@
 	if (!pmu || !cpumask_test_cpu(cpu, &pmu->supported_cpus))
 		return 0;
 
-	data.cmd = CPU_PM_ENTER;
-	cpu_pm_pmu_common(&data);
 	/* Disarm the PMU IRQ before disappearing. */
 	if (data.armpmu->pmu_state == ARM_PMU_STATE_RUNNING &&
 		data.armpmu->plat_device) {
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
index a62c939..235570e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -457,6 +457,7 @@
 	msm_mux_dbg_out,
 	msm_mux_gcc_plltest,
 	msm_mux_emac_pps,
+	msm_mux_gps_ext_aggressor,
 	msm_mux_NA,
 };
 
@@ -837,6 +838,10 @@
 	"gpio89",
 };
 
+static const char * const gps_ext_aggressor_groups[] = {
+	"gpio42",
+};
+
 static const struct msm_function sdxpoorwills_functions[] = {
 	FUNCTION(uim2_data),
 	FUNCTION(gpio),
@@ -956,6 +961,7 @@
 	FUNCTION(dbg_out),
 	FUNCTION(gcc_plltest),
 	FUNCTION(emac_pps),
+	FUNCTION(gps_ext_aggressor),
 };
 
 /* Every pin is maintained as a single group, and missing or non-existing pin
@@ -1033,7 +1039,8 @@
 	[39] = PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[40] = PINGROUP(40, NA, NA, cri_trng0, NA, NA, NA, NA, NA, NA),
 	[41] = PINGROUP(41, NA, NA, cri_trng1, NA, NA, NA, NA, NA, NA),
-	[42] = PINGROUP(42, nav_pps, nav_dr, pll_ref, NA, NA, NA, NA, NA, NA),
+	[42] = PINGROUP(42, nav_pps, gps_ext_aggressor, nav_dr, pll_ref, NA,
+			NA, NA, NA, NA),
 	[43] = PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[44] = PINGROUP(44, coex_uart, qdss_tracectl, NA, NA, NA, NA, NA, NA,
 			NA),
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index ebc3b8f..dde53ba 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -234,6 +234,7 @@
 	EP_PCIE_RES_DM_CORE,
 	EP_PCIE_RES_ELBI,
 	EP_PCIE_RES_IATU,
+	EP_PCIE_RES_TCSR_PERST,
 	EP_PCIE_MAX_RES,
 };
 
@@ -325,6 +326,7 @@
 	void __iomem                 *dm_core;
 	void __iomem                 *elbi;
 	void __iomem                 *iatu;
+	void __iomem		     *tcsr_perst_en;
 
 	struct msm_bus_scale_pdata   *bus_scale_table;
 	u32                          bus_client;
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index f69b7e1..7dc3aeb 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -91,6 +91,7 @@
 	{"dm_core",	NULL, NULL},
 	{"elbi",	NULL, NULL},
 	{"iatu",	NULL, NULL},
+	{"tcsr_pcie_perst_en",	NULL, NULL},
 };
 
 static const struct ep_pcie_irq_info_t ep_pcie_irq_info[EP_PCIE_MAX_IRQ] = {
@@ -527,6 +528,8 @@
 
 static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
 {
+	u32 mhi_status;
+
 	EP_PCIE_DBG(dev,
 		"Initial version of MMIO is:0x%x\n",
 		readl_relaxed(dev->mmio + PCIE20_MHIVER));
@@ -538,6 +541,14 @@
 		return;
 	}
 
+	mhi_status = readl_relaxed(dev->mmio + PCIE20_MHISTATUS);
+	if (mhi_status & BIT(2)) {
+		EP_PCIE_DBG(dev,
+			"MHISYS error is set:%d, proceed to MHI\n",
+			mhi_status);
+		return;
+	}
+
 	ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
 	ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
 	ep_pcie_write_reg(dev->mmio, PCIE20_MHICTRL, 0x0);
@@ -1219,6 +1230,7 @@
 	dev->dm_core = dev->res[EP_PCIE_RES_DM_CORE].base;
 	dev->elbi = dev->res[EP_PCIE_RES_ELBI].base;
 	dev->iatu = dev->res[EP_PCIE_RES_IATU].base;
+	dev->tcsr_perst_en = dev->res[EP_PCIE_RES_TCSR_PERST].base;
 
 out:
 	kfree(clkfreq);
@@ -1348,7 +1360,22 @@
 		}
 
 		dev->power_on = true;
-		/* check link status during initial bootup */
+
+		 EP_PCIE_DBG(dev,
+			 "TCSR PERST_EN value before configure:0x%x\n",
+			 readl_relaxed(dev->tcsr_perst_en + 0x258));
+
+		 /*
+		  * Delatch PERST_EN with TCSR to avoid device reset
+		  * during host reboot case.
+		  */
+		 writel_relaxed(0, dev->tcsr_perst_en + 0x258);
+
+		 EP_PCIE_DBG(dev,
+			 "TCSR PERST_EN value after configure:0x%x\n",
+			 readl_relaxed(dev->tcsr_perst_en));
+
+		 /* check link status during initial bootup */
 		if (!dev->enumerated) {
 			val = readl_relaxed(dev->parf + PCIE20_PARF_PM_STTS);
 			val = val & PARF_XMLH_LINK_UP;
@@ -1358,6 +1385,11 @@
 				EP_PCIE_INFO(dev,
 					"PCIe V%d: link initialized by bootloader for LE PCIe endpoint; skip link training in HLOS.\n",
 					dev->rev);
+				/*
+				 * Skip mhi mmio config for host reboot case
+				 * with bios-locking enabled.
+				 */
+				dev->config_mmio_init = true;
 				ep_pcie_core_init(dev, true);
 				dev->link_status = EP_PCIE_LINK_UP;
 				dev->l23_ready = false;
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
index 9693014..54e82f3a 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -675,9 +675,14 @@
 		return;
 	}
 
+	if (!data) {
+		IPA_GSB_ERR("Invalid data\n");
+		return;
+	}
+
 	skb = (struct sk_buff *)data;
 
-	while (skb && skb->len) {
+	while (skb->len) {
 		mux_hdr = (struct ipa_gsb_mux_hdr *)skb->data;
 		pkt_size = mux_hdr->pkt_size;
 		/* 4-byte padding */
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index 34ddd63..ae9dd62 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2019 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
@@ -1617,7 +1617,7 @@
 		res = ipa_mhi_read_write_host(IPA_MHI_DMA_TO_HOST,
 			&channel->state, channel->channel_context_addr +
 				offsetof(struct ipa_mhi_ch_ctx, chstate),
-				sizeof(channel->state));
+				sizeof(((struct ipa_mhi_ch_ctx *)0)->chstate));
 		if (res) {
 			IPA_MHI_ERR("ipa_mhi_read_write_host failed\n");
 			return res;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index ec1d4d9..335e796 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -1563,9 +1563,8 @@
 	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
 }
 
-static int ipa3_read_table(
+static void ipa3_read_table(
 	char *table_addr, u32 table_size,
-	char *buff, u32 buff_size,
 	u32 *total_num_entries,
 	u32 *rule_id,
 	enum ipahal_nat_type nat_type)
@@ -1575,18 +1574,27 @@
 	size_t entry_size;
 	bool entry_zeroed;
 	bool entry_valid;
-	u32 i, num_entries = 0, id = *rule_id, pos = 0;
+	u32 i, num_entries = 0, id = *rule_id;
+	char *buff;
+	size_t buff_size = 2 * IPA_MAX_ENTRY_STRING_LEN;
 
 	IPADBG("\n");
-
-	if (table_addr == NULL)
-		return 0;
+	if (table_addr == NULL) {
+		pr_err("NULL NAT table\n");
+		return;
+	}
 
 	result = ipahal_nat_entry_size(nat_type, &entry_size);
 	if (result) {
 		IPAERR("Failed to retrieve size of %s entry\n",
 			ipahal_nat_type_str(nat_type));
-		return 0;
+		return;
+	}
+
+	buff = kzalloc(buff_size, GFP_KERNEL);
+	if (!buff) {
+		IPAERR("Out of memory\n");
+		return;
 	}
 
 	for (i = 0, entry = table_addr;
@@ -1614,109 +1622,90 @@
 
 		if (entry_valid) {
 			++num_entries;
-			pos += scnprintf(buff + pos, buff_size - pos,
-				"\tEntry_Index=%d\n", id);
-		} else {
-			pos += scnprintf(buff + pos, buff_size - pos,
-				"\tEntry_Index=%d - Invalid Entry\n", id);
-		}
+			pr_err("\tEntry_Index=%d\n", id);
+		} else
+			pr_err("\tEntry_Index=%d - Invalid Entry\n", id);
 
-		pos += ipahal_nat_stringify_entry(nat_type, entry,
-			buff + pos, buff_size - pos);
+		ipahal_nat_stringify_entry(nat_type, entry,
+			buff, buff_size);
+		pr_err("%s\n", buff);
+		memset(buff, 0, buff_size);
 	}
 
 	if (num_entries)
-		pos += scnprintf(buff + pos, buff_size - pos, "\n");
+		pr_err("\n");
 	else
-		pos += scnprintf(buff + pos, buff_size - pos, "\tEmpty\n\n");
-
+		pr_err("\tEmpty\n\n");
 	IPADBG("return\n");
 bail:
+	kfree(buff);
 	*rule_id = id;
 	*total_num_entries += num_entries;
-	return pos;
 }
 
-static int ipa3_start_read_memory_device(
+static void ipa3_start_read_memory_device(
 	struct ipa3_nat_ipv6ct_common_mem *dev,
-	char *buff, u32 buff_size,
 	enum ipahal_nat_type nat_type,
 	u32 *num_entries)
 {
-	u32 rule_id = 0, pos = 0;
+	u32 rule_id = 0;
 
 	IPADBG("\n");
 
-	pos += scnprintf(buff + pos, buff_size - pos, "%s_Table_Size=%d\n",
+	pr_err("%s_Table_Size=%d\n",
 		dev->name, dev->table_entries + 1);
 
-	pos += scnprintf(buff + pos, buff_size - pos,
-		"%s_Expansion_Table_Size=%d\n",
+	pr_err("%s_Expansion_Table_Size=%d\n",
 		dev->name, dev->expn_table_entries);
 
 	if (!dev->is_sys_mem)
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"Not supported for local(shared) memory\n");
+		pr_err("Not supported for local(shared) memory\n");
 
-	pos += scnprintf(buff + pos, buff_size - pos,
-		"\n%s Base Table:\n", dev->name);
-	pos += ipa3_read_table(dev->base_table_addr, dev->table_entries + 1,
-		buff + pos, buff_size - pos, num_entries, &rule_id, nat_type);
+	pr_err("\n%s Base Table:\n", dev->name);
+	ipa3_read_table(dev->base_table_addr, dev->table_entries + 1,
+		num_entries, &rule_id, nat_type);
 
-	pos += scnprintf(buff + pos, buff_size - pos,
-		"%s Expansion Table:\n", dev->name);
-	pos += ipa3_read_table(
+	pr_err("%s Expansion Table:\n", dev->name);
+	ipa3_read_table(
 		dev->expansion_table_addr, dev->expn_table_entries,
-		buff + pos, buff_size - pos,
 		num_entries,
 		&rule_id,
 		nat_type);
 
 	IPADBG("return\n");
-	return pos;
 }
 
-static int ipa3_finish_read_memory_device(
+static void ipa3_finish_read_memory_device(
 	struct ipa3_nat_ipv6ct_common_mem *dev,
-	char *buff, u32 buff_size,
-	u32 curr_pos,
 	u32 num_entries)
 {
-	u32 pos = 0;
-
 	IPADBG("\n");
-
-	/*
-	 * A real buffer and buff size, so need to use the
-	 * real current position
-	 */
-	pos += scnprintf(buff + curr_pos, buff_size - curr_pos,
-		"Overall number %s entries: %d\n\n", dev->name, num_entries);
-
-	if (curr_pos + pos >= buff_size - 1)
-		IPAERR(
-			"The %s debug information is larger than the internal buffer, so the read information might be incomplete",
-			dev->name);
-
+	pr_err("Overall number %s entries: %d\n\n", dev->name, num_entries);
 	IPADBG("return\n");
-	return pos;
 }
 
-static int ipa3_read_pdn_table(char *buff, u32 buff_size)
+static void ipa3_read_pdn_table(void)
 {
 	int i, result;
 	char *pdn_entry;
 	size_t pdn_entry_size;
 	bool entry_zeroed;
 	bool entry_valid;
-	u32 pos = 0;
+	char *buff;
+	size_t buff_size = 128;
 
 	IPADBG("\n");
 
 	result = ipahal_nat_entry_size(IPAHAL_NAT_IPV4_PDN, &pdn_entry_size);
 	if (result) {
 		IPAERR("Failed to retrieve size of PDN entry");
-		return 0;
+		return;
+	}
+
+	buff = kzalloc(buff_size, GFP_KERNEL);
+	if (!buff) {
+		IPAERR("Out of memory\n");
+		return;
 	}
 
 	for (i = 0, pdn_entry = ipa3_ctx->nat_mem.pdn_mem.base;
@@ -1740,83 +1729,63 @@
 			goto bail;
 		}
 		if (entry_valid)
-			pos += scnprintf(buff + pos, buff_size - pos,
-				"PDN %d: ", i);
+			pr_err("PDN %d: ", i);
 		else
-			pos += scnprintf(buff + pos, buff_size - pos,
-				"PDN %d - Invalid: ", i);
+			pr_err("PDN %d - Invalid: ", i);
 
-		pos += ipahal_nat_stringify_entry(IPAHAL_NAT_IPV4_PDN,
-			pdn_entry, buff + pos, buff_size - pos);
+		ipahal_nat_stringify_entry(IPAHAL_NAT_IPV4_PDN,
+				pdn_entry, buff, buff_size);
+		pr_err("%s\n", buff);
+		memset(buff, 0, buff_size);
 	}
-	pos += scnprintf(buff + pos, buff_size - pos, "\n");
-
-	IPADBG("return\n");
+	pr_err("\n");
 bail:
-	return pos;
+	kfree(buff);
+	IPADBG("return\n");
 }
 
 static ssize_t ipa3_read_nat4(struct file *file,
 		char __user *ubuf, size_t count,
 		loff_t *ppos)
 {
-	ssize_t ret;
-	char *buff;
-	u32 rule_id = 0, pos = 0, num_entries = 0, index_num_entries = 0;
-	const u32 buff_size = IPA_MAX_MSG_LEN + 2 * IPA_MAX_ENTRY_STRING_LEN * (
-		ipa3_ctx->nat_mem.dev.table_entries + 1 +
-		ipa3_ctx->nat_mem.dev.expn_table_entries);
+	u32 rule_id = 0, num_entries = 0, index_num_entries = 0;
 
-	IPADBG("\n");
-
-	buff = kzalloc(buff_size, GFP_KERNEL);
-	if (buff == NULL)
-		return -ENOMEM;
-
+	pr_err("IPA3 NAT stats\n");
 	if (!ipa3_ctx->nat_mem.dev.is_dev_init) {
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"NAT hasn't been initialized or not supported\n");
+		pr_err("NAT hasn't been initialized or not supported\n");
 		goto ret;
 	}
 
 	mutex_lock(&ipa3_ctx->nat_mem.dev.lock);
 
 	if (!ipa3_ctx->nat_mem.dev.is_hw_init) {
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"NAT H/W hasn't been initialized\n");
+		pr_err("NAT H/W hasn't been initialized\n");
 		goto bail;
 	}
 
-	pos += scnprintf(buff + pos, buff_size - pos, "\n");
-
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
-		pos += ipa3_read_pdn_table(buff + pos, buff_size - pos);
+		ipa3_read_pdn_table();
 	} else {
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"NAT Table IP Address=%pI4h\n\n",
+		pr_err("NAT Table IP Address=%pI4h\n\n",
 			&ipa3_ctx->nat_mem.public_ip_addr);
 	}
 
-	pos += ipa3_start_read_memory_device(&ipa3_ctx->nat_mem.dev,
-		buff + pos, buff_size - pos, IPAHAL_NAT_IPV4, &num_entries);
+	ipa3_start_read_memory_device(&ipa3_ctx->nat_mem.dev,
+		IPAHAL_NAT_IPV4, &num_entries);
 
 	/* Print Index tables */
-	pos += scnprintf(buff + pos, buff_size - pos,
-		"ipaNatTable Index Table:\n");
-	pos += ipa3_read_table(
+	pr_err("ipaNatTable Index Table:\n");
+	ipa3_read_table(
 		ipa3_ctx->nat_mem.index_table_addr,
 		ipa3_ctx->nat_mem.dev.table_entries + 1,
-		buff + pos, buff_size - pos,
 		&index_num_entries,
 		&rule_id,
 		IPAHAL_NAT_IPV4_INDEX);
 
-	pos += scnprintf(buff + pos, buff_size - pos,
-		"ipaNatTable Expansion Index Table:\n");
-	pos += ipa3_read_table(
+	pr_err("ipaNatTable Expansion Index Table:\n");
+	ipa3_read_table(
 		ipa3_ctx->nat_mem.index_table_expansion_addr,
 		ipa3_ctx->nat_mem.dev.expn_table_entries,
-		buff + pos, buff_size - pos,
 		&index_num_entries,
 		&rule_id,
 		IPAHAL_NAT_IPV4_INDEX);
@@ -1826,62 +1795,43 @@
 			"The NAT table number of entries %d is different from index table number of entries %d\n",
 			num_entries, index_num_entries);
 
-	pos += ipa3_finish_read_memory_device(&ipa3_ctx->nat_mem.dev,
-		buff, buff_size, pos, num_entries);
+	ipa3_finish_read_memory_device(&ipa3_ctx->nat_mem.dev, num_entries);
 
 	IPADBG("return\n");
 bail:
 	mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
 ret:
-	ret = simple_read_from_buffer(ubuf, count, ppos, buff, pos);
-	kfree(buff);
-	return ret;
+	return 0;
 }
 
 static ssize_t ipa3_read_ipv6ct(struct file *file,
 	char __user *ubuf, size_t count,
 	loff_t *ppos) {
-	ssize_t ret;
-	char *buff;
-	u32 pos = 0, num_entries = 0;
-	const u32 buff_size = IPA_MAX_MSG_LEN + IPA_MAX_ENTRY_STRING_LEN * (
-		ipa3_ctx->nat_mem.dev.table_entries + 1 +
-		ipa3_ctx->nat_mem.dev.expn_table_entries);
+	u32 num_entries = 0;
 
-	IPADBG("\n");
-
-	buff = kzalloc(buff_size, GFP_KERNEL);
-	if (buff == NULL)
-		return 0;
-
-	pos += scnprintf(buff + pos, buff_size - pos, "\n");
+	pr_err("\n");
 
 	if (!ipa3_ctx->ipv6ct_mem.dev.is_dev_init) {
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"IPv6 connection tracking hasn't been initialized or not supported\n");
-		goto ret;
+		pr_err("IPv6 Conntrack not initialized or not supported\n");
+		return 0;
 	}
 
 	mutex_lock(&ipa3_ctx->ipv6ct_mem.dev.lock);
 
 	if (!ipa3_ctx->ipv6ct_mem.dev.is_hw_init) {
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"IPv6 connection tracking H/W hasn't been initialized\n");
+		pr_err("IPv6 connection tracking H/W hasn't been initialized\n");
 		goto bail;
 	}
 
-	pos += ipa3_start_read_memory_device(&ipa3_ctx->ipv6ct_mem.dev,
-		buff + pos, buff_size - pos, IPAHAL_NAT_IPV6CT, &num_entries);
-	pos += ipa3_finish_read_memory_device(&ipa3_ctx->ipv6ct_mem.dev,
-		buff, buff_size, pos, num_entries);
+	ipa3_start_read_memory_device(&ipa3_ctx->ipv6ct_mem.dev,
+		IPAHAL_NAT_IPV6CT, &num_entries);
+	ipa3_finish_read_memory_device(&ipa3_ctx->ipv6ct_mem.dev,
+		num_entries);
 
 	IPADBG("return\n");
 bail:
 	mutex_unlock(&ipa3_ctx->ipv6ct_mem.dev.lock);
-ret:
-	ret = simple_read_from_buffer(ubuf, count, ppos, buff, pos);
-	kfree(buff);
-	return ret;
+	return 0;
 }
 
 static ssize_t ipa3_rm_read_stats(struct file *file, char __user *ubuf,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 6f19081..3e6b365 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -4426,7 +4426,7 @@
 		return -EINVAL;
 	}
 
-	if (iface < 0 || iface > IPA_VLAN_IF_MAX) {
+	if (iface < 0 || iface >= IPA_VLAN_IF_MAX) {
 		IPAERR("invalid iface %d\n", iface);
 		return -EINVAL;
 	}
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index ade1f0c..d2a59ca 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -64,6 +64,7 @@
 #define TR_RING_ELEMENT_SZ	sizeof(struct mhi_dev_transfer_ring_element)
 #define RING_ELEMENT_TYPE_SZ	sizeof(union mhi_dev_ring_element_type)
 
+uint32_t bhi_imgtxdb;
 enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR;
 enum mhi_msg_level mhi_ipc_msg_lvl = MHI_MSG_VERBOSE;
 void *mhi_ipc_log;
@@ -940,8 +941,6 @@
 	struct mhi_addr host_addr;
 	struct mhi_dev_channel *ch;
 	struct mhi_dev_ring *ring;
-	char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL};
-	char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
 
 	ch_id = el->generic.chid;
 	mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n",
@@ -1027,9 +1026,7 @@
 		mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
 		/* Trigger callback to clients */
 		mhi_dev_trigger_cb(ch_id);
-		if (ch_id == MHI_CLIENT_MBIM_OUT)
-			kobject_uevent_env(&mhi_ctx->dev->kobj,
-						KOBJ_CHANGE, connected);
+		mhi_uci_chan_state_notify(mhi, ch_id, MHI_STATE_CONNECTED);
 		break;
 	case MHI_DEV_RING_EL_STOP:
 		if (ch_id >= HW_CHANNEL_BASE) {
@@ -1083,9 +1080,10 @@
 
 			mutex_unlock(&ch->ch_lock);
 			mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
-			if (ch_id == MHI_CLIENT_MBIM_OUT)
-				kobject_uevent_env(&mhi_ctx->dev->kobj,
-						KOBJ_CHANGE, disconnected);
+			/* Trigger callback to clients */
+			mhi_dev_trigger_cb(ch_id);
+			mhi_uci_chan_state_notify(mhi, ch_id,
+					MHI_STATE_DISCONNECTED);
 		}
 		break;
 	case MHI_DEV_RING_EL_RESET:
@@ -1159,9 +1157,9 @@
 				pr_err("Error sending command completion event\n");
 			mutex_unlock(&ch->ch_lock);
 			mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
-			if (ch_id == MHI_CLIENT_MBIM_OUT)
-				kobject_uevent_env(&mhi_ctx->dev->kobj,
-						KOBJ_CHANGE, disconnected);
+			mhi_dev_trigger_cb(ch_id);
+			mhi_uci_chan_state_notify(mhi, ch_id,
+					MHI_STATE_DISCONNECTED);
 		}
 		break;
 	default:
@@ -1324,13 +1322,28 @@
 	}
 }
 
+static void mhi_update_state_info_all(enum mhi_ctrl_info info)
+{
+	int i;
+	struct mhi_dev_client_cb_reason reason;
+
+	mhi_ctx->ctrl_info = info;
+	for (i = 0; i < MHI_MAX_CHANNELS; ++i) {
+		channel_state_info[i].ctrl_info = info;
+		/* Notify kernel clients */
+		mhi_dev_trigger_cb(i);
+	}
+
+	/* For legacy reasons for QTI client */
+	reason.reason = MHI_DEV_CTRL_UPDATE;
+	uci_ctrl_update(&reason);
+}
+
 static int mhi_dev_abort(struct mhi_dev *mhi)
 {
 	struct mhi_dev_channel *ch;
 	struct mhi_dev_ring *ring;
 	int ch_id = 0, rc = 0;
-	char *disconnected_12[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
-	char *disconnected_14[2] = { "MHI_CHANNEL_STATE_14=DISCONNECTED", NULL};
 
 	/* Hard stop all the channels */
 	for (ch_id = 0; ch_id < mhi->cfg.channels; ch_id++) {
@@ -1344,19 +1357,9 @@
 		mutex_unlock(&ch->ch_lock);
 	}
 
-	/* Update ctrl node */
-	mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED);
-	mhi_update_state_info(MHI_CLIENT_MBIM_OUT, MHI_STATE_DISCONNECTED);
-	mhi_update_state_info(MHI_CLIENT_QMI_OUT, MHI_STATE_DISCONNECTED);
-	rc = kobject_uevent_env(&mhi_ctx->dev->kobj,
-				KOBJ_CHANGE, disconnected_12);
-	if (rc)
-		pr_err("Error sending uevent:%d\n", rc);
-
-	rc = kobject_uevent_env(&mhi_ctx->dev->kobj,
-				KOBJ_CHANGE, disconnected_14);
-	if (rc)
-		pr_err("Error sending uevent:%d\n", rc);
+	/* Update channel state and notify clients */
+	mhi_update_state_info_all(MHI_STATE_DISCONNECTED);
+	mhi_uci_chan_state_notify_all(mhi, MHI_STATE_DISCONNECTED);
 
 	flush_workqueue(mhi->ring_init_wq);
 	flush_workqueue(mhi->pending_ring_wq);
@@ -1496,8 +1499,7 @@
 	struct mhi_dev_ring *ring;
 	enum mhi_dev_state state;
 	enum mhi_dev_event event = 0;
-	bool mhi_reset = false;
-	uint32_t bhi_imgtxdb = 0;
+	u32 mhi_reset;
 
 	mutex_lock(&mhi_ctx->mhi_lock);
 	/* Check for interrupts */
@@ -1506,6 +1508,10 @@
 	if (int_value & MHI_MMIO_CTRL_INT_STATUS_A7_MSK) {
 		mhi_log(MHI_MSG_VERBOSE,
 			"processing ctrl interrupt with %d\n", int_value);
+
+		rc = mhi_dev_mmio_read(mhi, BHI_IMGTXDB, &bhi_imgtxdb);
+		mhi_log(MHI_MSG_DBG, "BHI_IMGTXDB = 0x%x\n", bhi_imgtxdb);
+
 		rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
 		if (rc) {
 			pr_err("%s: get mhi state failed\n", __func__);
@@ -1535,10 +1541,6 @@
 			pr_err("error sending SM event\n");
 			goto fail;
 		}
-
-		rc = mhi_dev_mmio_read(mhi, BHI_IMGTXDB, &bhi_imgtxdb);
-		mhi_log(MHI_MSG_VERBOSE,
-			"BHI_IMGTXDB = 0x%x\n", bhi_imgtxdb);
 	}
 
 	if (int_value & MHI_MMIO_CTRL_CRDB_STATUS_MSK) {
@@ -2371,7 +2373,7 @@
 {
 	int rc = 0;
 	uint32_t syserr, max_cnt = 0, bhi_intvec = 0;
-	bool mhi_reset;
+	u32 mhi_reset;
 	enum mhi_dev_state state;
 
 	/* Check if MHI is in syserr */
@@ -2381,6 +2383,16 @@
 
 	mhi_log(MHI_MSG_VERBOSE, "mhi_syserr = 0x%X\n", syserr);
 	if (syserr) {
+		/* Poll for the host to set the reset bit */
+		rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
+		if (rc) {
+			pr_err("%s: get mhi state failed\n", __func__);
+			return rc;
+		}
+
+		mhi_log(MHI_MSG_VERBOSE, "mhi_state = 0x%X, reset = %d\n",
+				state, mhi_reset);
+
 		rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec);
 		if (rc)
 			return rc;
@@ -2400,7 +2412,11 @@
 			pr_err("%s: get mhi state failed\n", __func__);
 			return rc;
 		}
-		while (mhi_reset != true && max_cnt < MHI_SUSPEND_TIMEOUT) {
+
+		mhi_log(MHI_MSG_VERBOSE, "mhi_state = 0x%X, reset = %d\n",
+				state, mhi_reset);
+
+		while (mhi_reset != 0x1 && max_cnt < MHI_SUSPEND_TIMEOUT) {
 			/* Wait for Host to set the reset */
 			msleep(MHI_SUSPEND_MIN);
 			rc = mhi_dev_mmio_get_mhi_state(mhi, &state,
@@ -2431,7 +2447,7 @@
 	struct ep_pcie_msi_config msi_cfg;
 	struct mhi_dev *mhi = container_of(work,
 				struct mhi_dev, ring_init_cb_work);
-	bool mhi_reset;
+	u32 mhi_reset;
 	enum mhi_dev_state state;
 	uint32_t max_cnt = 0, bhi_intvec = 0;
 
@@ -2900,6 +2916,15 @@
 	struct platform_device *pdev;
 	int rc = 0;
 
+	/*
+	 * There could be multiple calls to this function if device gets
+	 * multiple link-up events (bme irqs).
+	 */
+	if (mhi_ctx->init_done) {
+		mhi_log(MHI_MSG_INFO, "mhi init already done, returning\n");
+		return 0;
+	}
+
 	pdev = mhi_ctx->pdev;
 
 	INIT_WORK(&mhi_ctx->chdb_ctrl_work, mhi_dev_scheduler);
@@ -3027,6 +3052,8 @@
 		disable_irq(mhi_ctx->mhi_irq);
 	}
 
+	mhi_ctx->init_done = true;
+
 	return 0;
 }
 
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index fae39e0..5c03fb5 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -564,6 +564,9 @@
 	/* iATU is required to map control and data region */
 	bool				config_iatu;
 
+	/* Indicates if mhi init is done */
+	bool				init_done;
+
 	/* MHI state info */
 	enum mhi_ctrl_info		ctrl_info;
 
@@ -587,6 +590,7 @@
 	MHI_MSG_reserved = 0x80000000
 };
 
+extern uint32_t bhi_imgtxdb;
 extern enum mhi_msg_level mhi_msg_lvl;
 extern enum mhi_msg_level mhi_ipc_msg_lvl;
 extern void *mhi_ipc_log;
@@ -597,7 +601,7 @@
 	} \
 	if (mhi_ipc_log && (_msg_lvl >= mhi_ipc_msg_lvl)) { \
 		ipc_log_string(mhi_ipc_log,                     \
-			"[%s] " _msg, __func__, ##__VA_ARGS__);     \
+		"[0x%x %s] " _msg, bhi_imgtxdb, __func__, ##__VA_ARGS__);     \
 	} \
 } while (0)
 
@@ -982,7 +986,7 @@
  * @mhi_reset:	MHI device reset from host.
  */
 int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state,
-						bool *mhi_reset);
+						u32 *mhi_reset);
 
 /**
  * mhi_dev_mmio_init() - Initializes the MMIO and reads the Number of event
@@ -1092,5 +1096,17 @@
 void mhi_dev_notify_a7_event(struct mhi_dev *mhi);
 
 void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason);
+/**
+ * mhi_uci_chan_state_notify_all - Notifies channel state updates for
+ *				all clients who have uevents enabled.
+ */
+void mhi_uci_chan_state_notify_all(struct mhi_dev *mhi,
+		enum mhi_ctrl_info ch_state);
+/**
+ * mhi_uci_chan_state_notify - Notifies channel state update to the client
+ *				if uevents are enabled.
+ */
+void mhi_uci_chan_state_notify(struct mhi_dev *mhi,
+		enum mhi_client_channel ch_id, enum mhi_ctrl_info ch_state);
 
 #endif /* _MHI_H */
diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c
index 28d465a..22cf671 100644
--- a/drivers/platform/msm/mhi_dev/mhi_mmio.c
+++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c
@@ -259,7 +259,7 @@
 EXPORT_SYMBOL(mhi_dev_mmio_disable_erdb_a7);
 
 int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state,
-						bool *mhi_reset)
+						u32 *mhi_reset)
 {
 	uint32_t reg_value = 0;
 	int rc = 0;
@@ -279,9 +279,12 @@
 		return rc;
 
 	if (reg_value & MHICTRL_RESET_MASK)
-		*mhi_reset = true;
+		*mhi_reset = 1;
+	else
+		*mhi_reset = 0;
 
-	pr_debug("MHICTRL is 0x%x\n", reg_value);
+	mhi_log(MHI_MSG_VERBOSE, "MHICTRL is 0x%x, reset:%d\n",
+			reg_value, *mhi_reset);
 
 	return 0;
 }
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index 87dddfd..52bb535 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015,2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015,2017-2019, 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
@@ -83,6 +83,8 @@
 	void (*tre_notif_cb)(struct mhi_dev_client_cb_reason *reason);
 	/* Write completion - false if not needed */
 	bool wr_cmpl;
+	/* Uevent broadcast of channel state */
+	bool state_bcast;
 
 };
 
@@ -146,7 +148,10 @@
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
 		NULL,
-		NULL
+		NULL,
+		NULL,
+		false,
+		true
 	},
 	{
 		MHI_CLIENT_MBIM_IN,
@@ -162,7 +167,10 @@
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
 		NULL,
-		NULL
+		NULL,
+		NULL,
+		false,
+		true
 	},
 	{
 		MHI_CLIENT_QMI_IN,
@@ -1143,6 +1151,71 @@
 
 }
 
+void mhi_uci_chan_state_notify_all(struct mhi_dev *mhi,
+		enum mhi_ctrl_info ch_state)
+{
+	unsigned int i;
+	const struct chan_attr *chan_attrib;
+
+	for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i++) {
+		chan_attrib = &uci_chan_attr_table[i];
+		if (chan_attrib->state_bcast) {
+			uci_log(UCI_DBG_ERROR, "Calling notify for ch %d\n",
+					chan_attrib->chan_id);
+			mhi_uci_chan_state_notify(mhi, chan_attrib->chan_id,
+					ch_state);
+		}
+	}
+}
+EXPORT_SYMBOL(mhi_uci_chan_state_notify_all);
+
+void mhi_uci_chan_state_notify(struct mhi_dev *mhi,
+		enum mhi_client_channel ch_id, enum mhi_ctrl_info ch_state)
+{
+	struct uci_client *uci_handle;
+	char *buf[2];
+	int rc;
+
+	if (ch_id < 0 || ch_id >= MHI_MAX_SOFTWARE_CHANNELS) {
+		uci_log(UCI_DBG_ERROR, "Invalid chan %d\n", ch_id);
+		return;
+	}
+
+	uci_handle = &uci_ctxt.client_handles[CHAN_TO_CLIENT(ch_id)];
+	if (!uci_handle->in_chan_attr ||
+		!uci_handle->in_chan_attr->state_bcast) {
+		uci_log(UCI_DBG_VERBOSE, "Uevents not enabled for chan %d\n",
+				ch_id);
+		return;
+	}
+
+	if (ch_state == MHI_STATE_CONNECTED) {
+		buf[0] = kasprintf(GFP_KERNEL,
+				"MHI_CHANNEL_STATE_%d=CONNECTED", ch_id);
+		buf[1] = NULL;
+	} else if (ch_state == MHI_STATE_DISCONNECTED) {
+		buf[0] = kasprintf(GFP_KERNEL,
+				"MHI_CHANNEL_STATE_%d=DISCONNECTED", ch_id);
+		buf[1] = NULL;
+	} else {
+		uci_log(UCI_DBG_ERROR, "Unsupported chan state %d\n", ch_state);
+		return;
+	}
+
+	if (!buf[0]) {
+		uci_log(UCI_DBG_ERROR, "kasprintf failed for uevent buf!\n");
+		return;
+	}
+
+	rc = kobject_uevent_env(&mhi->dev->kobj, KOBJ_CHANGE, buf);
+	if (rc)
+		uci_log(UCI_DBG_ERROR,
+				"Sending uevent failed for chan %d\n", ch_id);
+
+	kfree(buf[0]);
+}
+EXPORT_SYMBOL(mhi_uci_chan_state_notify);
+
 void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason)
 {
 	struct uci_ctrl *uci_ctrl_handle = NULL;
@@ -1521,6 +1594,26 @@
 		uci_ctxt.at_ctrl_wq =
 			create_singlethread_workqueue("mhi_at_ctrl_wq");
 		INIT_WORK(&uci_ctxt.at_ctrl_work, mhi_uci_at_ctrl_read);
+	} else if (cb_data->ctrl_info == MHI_STATE_DISCONNECTED) {
+		if (uci_ctxt.at_ctrl_wq == NULL) {
+			uci_log(UCI_DBG_VERBOSE,
+				"Disconnect already processed for at ctrl channels\n");
+			return;
+		}
+		destroy_workqueue(uci_ctxt.at_ctrl_wq);
+		uci_ctxt.at_ctrl_wq = NULL;
+		if (!(client->f_flags & O_SYNC))
+			kfree(client->wreqs);
+		rc = mhi_dev_close_channel(client->out_handle);
+		if (rc)
+			uci_log(UCI_DBG_INFO,
+			"Failed to close channel %d ret %d\n",
+			client->out_chan, rc);
+		rc = mhi_dev_close_channel(client->in_handle);
+		if (rc)
+			uci_log(UCI_DBG_INFO,
+			"Failed to close channel %d ret %d\n",
+			client->in_chan, rc);
 	}
 }
 
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 07715b7..ec438df 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -341,6 +341,7 @@
 	POWER_SUPPLY_ATTR(qc_opti_disable),
 	POWER_SUPPLY_ATTR(fcc_stepper_enable),
 	POWER_SUPPLY_ATTR(cc_soc),
+	POWER_SUPPLY_ATTR(qg_vbms_mode),
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_ATTR(charge_counter_ext),
 	/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
index f3f2c66..09c3fc4 100644
--- a/drivers/power/supply/qcom/fg-alg.c
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -1055,9 +1055,19 @@
 	struct ttf *ttf = container_of(work,
 				struct ttf, ttf_work.work);
 	int rc, ibatt_now, vbatt_now, ttf_now, charge_status;
+	int valid = 0;
 	ktime_t ktime_now;
 
 	mutex_lock(&ttf->lock);
+	rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+	if (rc < 0) {
+		pr_err("failed to get ttf_valid rc=%d\n", rc);
+		goto end_work;
+	}
+
+	if (!valid)
+		goto end_work;
+
 	rc =  ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
 	if (rc < 0) {
 		pr_err("failed to get charge_status rc=%d\n", rc);
@@ -1198,7 +1208,16 @@
  */
 void ttf_update(struct ttf *ttf, bool input_present)
 {
-	int delay_ms;
+	int delay_ms, rc, valid = 0;
+
+	rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+	if (rc < 0) {
+		pr_err("failed to get ttf_valid rc=%d\n", rc);
+		return;
+	}
+
+	if (!valid)
+		return;
 
 	if (ttf->input_present == input_present)
 		return;
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index 4f0773b..6f5f9f1 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -64,6 +64,7 @@
 	bool			esr_disable;
 	bool			esr_discharge_enable;
 	bool			qg_ext_sense;
+	bool			qg_vbms_mode;
 };
 
 struct qg_esr_data {
@@ -128,6 +129,7 @@
 	int			esr_nominal;
 	int			soh;
 	int			soc_reporting_ready;
+	int			vbms_ibat_ua;
 	u32			fifo_done_count;
 	u32			wa_flags;
 	u32			seq_no;
diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index 894e076..69f2e1e 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -121,6 +121,7 @@
 #define QG_SDAM_MAX_OFFSET			0xA4
 
 /* Below offset is used by PBS */
+#define QG_SDAM_SEQ_OFFSET			0xBB /* 1-byte 0xBB */
 #define QG_SDAM_PON_OCV_OFFSET			0xBC /* 2-byte 0xBC-0xBD */
 
 #endif
diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c
index a3e045e..3b5065a 100644
--- a/drivers/power/supply/qcom/qg-util.c
+++ b/drivers/power/supply/qcom/qg-util.c
@@ -342,6 +342,11 @@
 		return 0;
 	}
 
+	if (chip->dt.qg_vbms_mode) {
+		*ibat_ua = chip->vbms_ibat_ua;
+		return 0;
+	}
+
 	/* hold data */
 	rc = qg_masked_write(chip, chip->qg_base + QG_DATA_CTL2_REG,
 				BURST_AVG_HOLD_FOR_READ_BIT,
diff --git a/drivers/power/supply/qcom/qpnp-linear-charger.c b/drivers/power/supply/qcom/qpnp-linear-charger.c
index 6e3158a..515ea35 100644
--- a/drivers/power/supply/qcom/qpnp-linear-charger.c
+++ b/drivers/power/supply/qcom/qpnp-linear-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2017-2019, 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
@@ -414,6 +414,7 @@
 	struct qpnp_adc_tm_chip		*adc_tm_dev;
 	struct led_classdev		led_cdev;
 	struct dentry			*debug_root;
+	struct work_struct		debug_board_work;
 
 	/* parallel-chg params */
 	struct power_supply		*parallel_psy;
@@ -1496,7 +1497,7 @@
 		return -EINVAL;
 	}
 
-	if (chip->cfg_use_fake_battery)
+	if (chip->cfg_use_fake_battery || chip->debug_board)
 		return 0;
 
 	mutex_lock(&chip->jeita_configure_lock);
@@ -1550,6 +1551,22 @@
 	return rc;
 }
 
+static void qpnp_lbc_debug_board_work_fn(struct work_struct *work)
+{
+	struct qpnp_lbc_chip *chip = container_of(work, struct qpnp_lbc_chip,
+						debug_board_work);
+	int rc = 0;
+
+	if (chip->adc_param.channel == LR_MUX1_BATT_THERM
+					&& chip->debug_board) {
+		pr_debug("Disable adc-tm notifications for debug board\n");
+		rc = qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
+							 &chip->adc_param);
+		if (rc < 0)
+			pr_err("failed to disable tm %d\n", rc);
+	}
+}
+
 static int qpnp_batt_property_is_writeable(struct power_supply *psy,
 					enum power_supply_property psp)
 {
@@ -1663,6 +1680,7 @@
 		break;
 	case POWER_SUPPLY_PROP_DEBUG_BATTERY:
 		chip->debug_board = val->intval;
+		schedule_work(&chip->debug_board_work);
 		rc = qpnp_lbc_charger_enable(chip, DEBUG_BOARD,
 						!(val->intval));
 		break;
@@ -2679,6 +2697,9 @@
 	struct qpnp_lbc_chip *chip = _chip;
 	int batt_present;
 
+	if (chip->debug_board)
+		return IRQ_HANDLED;
+
 	batt_present = qpnp_lbc_is_batt_present(chip);
 	pr_debug("batt-pres triggered: %d\n", batt_present);
 
@@ -3343,7 +3364,7 @@
 	alarm_init(&chip->vddtrim_alarm, ALARM_REALTIME, vddtrim_callback);
 	INIT_DELAYED_WORK(&chip->collapsible_detection_work,
 			qpnp_lbc_collapsible_detection_work);
-
+	INIT_WORK(&chip->debug_board_work, qpnp_lbc_debug_board_work_fn);
 	/* Get all device-tree properties */
 	rc = qpnp_charger_read_dt_props(chip);
 	if (rc) {
@@ -3553,6 +3574,7 @@
 		alarm_cancel(&chip->vddtrim_alarm);
 		cancel_work_sync(&chip->vddtrim_work);
 	}
+	cancel_work_sync(&chip->debug_board_work);
 	cancel_delayed_work_sync(&chip->collapsible_detection_work);
 	debugfs_remove_recursive(chip->debug_root);
 	if (chip->bat_if_base)
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 70c8a3b..5030352 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019 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
@@ -1029,6 +1029,9 @@
 	if (chip->udata.param[QG_FULL_SOC].valid)
 		chip->full_soc = chip->udata.param[QG_FULL_SOC].data;
 
+	if (chip->udata.param[QG_VBMS_IBAT].valid)
+		chip->vbms_ibat_ua = chip->udata.param[QG_VBMS_IBAT].data;
+
 	if (chip->udata.param[QG_SOC].valid ||
 			chip->udata.param[QG_SYS_SOC].valid) {
 
@@ -1061,10 +1064,6 @@
 			pr_err("Failed to update SDAM params, rc=%d\n", rc);
 	}
 
-	if (chip->udata.param[QG_CHARGE_COUNTER].valid)
-		chip->charge_counter_uah =
-			chip->udata.param[QG_CHARGE_COUNTER].data;
-
 	if (chip->udata.param[QG_ESR].valid)
 		chip->esr_last = chip->udata.param[QG_ESR].data;
 
@@ -1545,6 +1544,26 @@
 	return 0;
 }
 
+static int qg_get_charge_counter(struct qpnp_qg *chip, int *charge_counter)
+{
+	int rc, cc_soc = 0;
+	int64_t temp = 0;
+
+	rc = qg_get_learned_capacity(chip, &temp);
+	if (rc < 0 || !temp)
+		rc = qg_get_nominal_capacity((int *)&temp, 250, true);
+
+	if (rc < 0) {
+		pr_err("Failed to get FCC for charge-counter rc=%d\n", rc);
+		return rc;
+	}
+
+	cc_soc = CAP(0, 100, DIV_ROUND_CLOSEST(chip->cc_soc, 100));
+	*charge_counter = div_s64(temp * cc_soc, 100);
+
+	return 0;
+}
+
 static int qg_get_ttf_param(void *data, enum ttf_param param, int *val)
 {
 	union power_supply_propval prop = {0, };
@@ -1557,7 +1576,8 @@
 
 	switch (param) {
 	case TTF_VALID:
-		*val = (!chip->battery_missing && chip->profile_loaded);
+		*val = (!chip->battery_missing && chip->profile_loaded &&
+				!chip->dt.qg_vbms_mode);
 		break;
 	case TTF_MSOC:
 		rc = qg_get_battery_capacity(chip, val);
@@ -1732,7 +1752,7 @@
 		pval->intval = chip->bp.qg_profile_version;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
-		pval->intval = chip->charge_counter_uah;
+		rc = qg_get_charge_counter(chip, &pval->intval);
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL:
 		if (!chip->dt.cl_disable && chip->dt.cl_feedback_on)
@@ -1775,6 +1795,9 @@
 	case POWER_SUPPLY_PROP_CC_SOC:
 		rc = qg_get_cc_soc(chip, &pval->intval);
 		break;
+	case POWER_SUPPLY_PROP_QG_VBMS_MODE:
+		pval->intval = !!chip->dt.qg_vbms_mode;
+		break;
 	default:
 		pr_debug("Unsupported property %d\n", psp);
 		break;
@@ -1826,6 +1849,7 @@
 	POWER_SUPPLY_PROP_ESR_NOMINAL,
 	POWER_SUPPLY_PROP_SOH,
 	POWER_SUPPLY_PROP_CC_SOC,
+	POWER_SUPPLY_PROP_QG_VBMS_MODE,
 };
 
 static const struct power_supply_desc qg_psy_desc = {
@@ -2655,6 +2679,7 @@
 			pr_err("Failed to lookup FULL_SOC@PON rc=%d\n", rc);
 			goto done;
 		}
+		full_soc = CAP(0, 99, full_soc);
 
 		rc = lookup_soc_ocv(&cutoff_soc,
 				chip->dt.vbatt_cutoff_mv * 1000,
@@ -2672,7 +2697,7 @@
 
 		qg_dbg(chip, QG_DEBUG_PON, "v_float=%d v_cutoff=%d FULL_SOC=%d CUTOFF_SOC=%d PON_SYS_SOC=%d pon_soc=%d\n",
 			chip->bp.float_volt_uv, chip->dt.vbatt_cutoff_mv * 1000,
-			full_soc, cutoff_soc, pon_soc, soc);
+			full_soc, cutoff_soc, soc, pon_soc);
 	}
 done:
 	if (rc < 0) {
@@ -2822,6 +2847,9 @@
 		}
 	}
 
+	if (chip->dt.qg_vbms_mode)
+		chip->dt.s3_entry_fifo_length = 1;
+
 	if (chip->dt.s3_entry_fifo_length != -EINVAL) {
 		if (chip->dt.s3_entry_fifo_length < 1)
 			chip->dt.s3_entry_fifo_length = 1;
@@ -2939,6 +2967,11 @@
 				PROFILE_IRQ_DISABLE, true, 0);
 	}
 
+	if (chip->dt.qg_vbms_mode) {
+		chip->dt.esr_disable = true;
+		chip->dt.cl_disable = true;
+	}
+
 	/* restore ESR data */
 	if (!chip->dt.esr_disable)
 		qg_retrieve_esr_params(chip);
@@ -3426,18 +3459,24 @@
 			chip->cl->dt.min_start_soc, chip->cl->dt.max_start_soc,
 			chip->cl->dt.min_temp, chip->cl->dt.max_temp);
 	}
-	qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d ext-sns=%d\n",
+
+	chip->dt.qg_vbms_mode = of_property_read_bool(node,
+					"qcom,qg-vbms-mode");
+
+	qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d ext-sns=%d qg_vbms_mode=%d\n",
 			chip->dt.vbatt_empty_mv, chip->dt.vbatt_low_mv,
-			chip->dt.delta_soc, chip->dt.qg_ext_sense);
+			chip->dt.delta_soc, chip->dt.qg_ext_sense,
+			chip->dt.qg_vbms_mode);
 
 	return 0;
 }
 
 static int process_suspend(struct qpnp_qg *chip)
 {
-	u8 status = 0;
+	u8 status = 0, val;
 	int rc;
 	u32 fifo_rt_length = 0, sleep_fifo_length = 0;
+	bool process_fifo = false;
 
 	/* skip if profile is not loaded */
 	if (!chip->profile_loaded)
@@ -3447,6 +3486,12 @@
 
 	chip->suspend_data = false;
 
+	val = (chip->seq_no % 128) + 1;
+	rc = qg_sdam_multibyte_write(QG_SDAM_SEQ_OFFSET, &val, 1);
+	if (rc < 0) {
+		pr_err("Failed to write sdam seq, rc=%d\n", rc);
+		return rc;
+	}
 	/* read STATUS2 register to clear its last state */
 	qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status, 1);
 
@@ -3474,7 +3519,13 @@
 	 * the the #fifo to enter sleep, save the FIFO data
 	 * and reset the fifo count.
 	 */
-	if (fifo_rt_length >= (chip->dt.s2_fifo_length - sleep_fifo_length)) {
+	if (chip->dt.qg_vbms_mode && fifo_rt_length >= 1)
+		process_fifo = true;
+	else if (fifo_rt_length >=
+			(chip->dt.s2_fifo_length - sleep_fifo_length))
+		process_fifo = true;
+
+	if (process_fifo) {
 		rc = qg_master_hold(chip, true);
 		if (rc < 0) {
 			pr_err("Failed to hold master, rc=%d\n", rc);
@@ -3508,7 +3559,7 @@
 
 static int process_resume(struct qpnp_qg *chip)
 {
-	u8 status2 = 0, rt_status = 0;
+	u8 status2 = 0, rt_status = 0, val = 0;
 	u32 ocv_uv = 0, ocv_raw = 0;
 	int rc;
 
@@ -3564,6 +3615,11 @@
 		chip->suspend_data = false;
 	}
 
+	rc = qg_sdam_multibyte_write(QG_SDAM_SEQ_OFFSET, &val, 1);
+	if (rc < 0) {
+		pr_err("Failed to write sdam seq, rc=%d\n", rc);
+		return rc;
+	}
 	schedule_delayed_work(&chip->ttf->ttf_work, 0);
 
 	return rc;
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 0a677ec..7994741 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -282,7 +282,8 @@
 		break;
 	case PMI632_SUBTYPE:
 		chip->chg.smb_version = PMI632_SUBTYPE;
-		chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA;
+		chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA |
+					CHG_TERMINATION_WA;
 		if (pmic_rev_id->rev4 >= 2)
 			chg->wa_flags |= MOISTURE_PROTECTION_WA;
 		chg->param = smb5_pmi632_params;
diff --git a/drivers/power/supply/qcom/qpnp-vm-bms.c b/drivers/power/supply/qcom/qpnp-vm-bms.c
index ef05178..9caced7 100644
--- a/drivers/power/supply/qcom/qpnp-vm-bms.c
+++ b/drivers/power/supply/qcom/qpnp-vm-bms.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019, 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
@@ -1863,6 +1863,10 @@
 {
 	int rc;
 
+	if (is_debug_batt_id(chip)) {
+		pr_debug("skip configuring vbat monitoring for debug_board\n");
+		return 0;
+	}
 	chip->vbat_monitor_params.low_thr =
 					chip->dt.cfg_low_voltage_threshold;
 	chip->vbat_monitor_params.high_thr =
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 3671891..3885fbf 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -2888,6 +2888,7 @@
 
 	chg->pd_active = pd_active;
 	if (chg->pd_active) {
+		chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
 		vote(chg->apsd_disable_votable, PD_VOTER, true, 0);
 		vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
 		vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
diff --git a/drivers/power/supply/qcom/smb1360-charger-fg.c b/drivers/power/supply/qcom/smb1360-charger-fg.c
index 4e98ec7..41dcf1d 100644
--- a/drivers/power/supply/qcom/smb1360-charger-fg.c
+++ b/drivers/power/supply/qcom/smb1360-charger-fg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018-2019, 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
@@ -31,6 +31,7 @@
 #include <linux/qpnp/qpnp-adc.h>
 #include <linux/completion.h>
 #include <linux/pm_wakeup.h>
+#include <linux/of_irq.h>
 
 #define _SMB1360_MASK(BITS, POS) \
 	((unsigned char)(((1 << (BITS)) - 1) << (POS)))
@@ -405,6 +406,7 @@
 	bool				otg_fet_present;
 	bool				fet_gain_enabled;
 	int				otg_fet_enable_gpio;
+	int				usb_id_gpio;
 
 	/* status tracking */
 	int				voltage_now;
@@ -466,6 +468,7 @@
 	int				cold_hysteresis;
 	int				hot_hysteresis;
 	struct extcon_dev		*extcon;
+	int				usb_id_irq;
 };
 
 static int chg_time[] = {
@@ -2885,6 +2888,28 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t smb1360_usb_id_irq_handler(int irq, void *dev_id)
+{
+	struct smb1360_chip *chip = dev_id;
+	int rc = 0;
+	bool id_state;
+
+	id_state = gpio_get_value(chip->usb_id_gpio);
+
+	rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT,
+					!id_state ? CMD_OTG_EN_BIT : 0);
+	if (rc) {
+		pr_err("Couldn't enable  OTG mode rc=%d\n", rc);
+		return IRQ_HANDLED;
+	}
+	extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST,
+					!id_state ? true : false);
+
+	pr_debug("usb_id_irq triggered, id_state = %d\n", id_state);
+
+	return IRQ_HANDLED;
+}
+
 static int show_irq_count(struct seq_file *m, void *data)
 {
 	int i, j, total = 0;
@@ -3421,6 +3446,10 @@
 	int rc = 0;
 	struct regulator_config cfg = {};
 
+	/* OTG is enabled by SMB1360 if usb-id config is defined */
+	if (chip->usb_id_gpio > 0 && chip->usb_id_irq > 0)
+		return 0;
+
 	chip->otg_vreg.rdesc.owner = THIS_MODULE;
 	chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
 	chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops;
@@ -3557,6 +3586,7 @@
 {
 	int rc;
 	u8 reg = 0;
+	bool id_state;
 
 	/*
 	 * It is okay to read the IRQ status as the irq's are
@@ -3621,6 +3651,25 @@
 	else
 		extcon_set_cable_state_(chip->extcon, EXTCON_USB, true);
 
+	pr_debug("usb %s at boot\n", chip->usb_present ? "present" : "absent");
+
+	/*check otg presence and notify*/
+	if (chip->usb_id_gpio != -EINVAL) {
+		id_state = gpio_get_value(chip->usb_id_gpio);
+		/* usb-id is low, enable OTG */
+		if (!id_state) {
+			rc = smb1360_masked_write(chip, CMD_CHG_REG,
+						CMD_OTG_EN_BIT, CMD_OTG_EN_BIT);
+			if (rc) {
+				pr_err("Couldn't enable  OTG mode rc=%d\n", rc);
+				return rc;
+			}
+			extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST,
+									true);
+			pr_debug("OTG enabled at boot\n");
+		}
+	}
+
 	power_supply_changed(chip->usb_psy);
 	return 0;
 }
@@ -4752,6 +4801,11 @@
 			return rc;
 		}
 	}
+	chip->usb_id_gpio = -EINVAL;
+	if (of_find_property(node, "qcom,usb-id-gpio", NULL)) {
+		chip->usb_id_gpio = of_get_named_gpio(node,
+					"qcom,usb-id-gpio", 0);
+	}
 
 	chip->pulsed_irq = of_property_read_bool(node, "qcom,stat-pulsed-irq");
 
@@ -5073,6 +5127,28 @@
 		enable_irq_wake(client->irq);
 	}
 
+	chip->usb_id_irq = of_irq_get_byname(chip->dev->of_node,
+						"smb1360_usb_id_irq");
+	if (chip->usb_id_irq > 0) {
+		if (chip->usb_id_gpio == -EINVAL) {
+			pr_err("usb-id gpio not defined\n");
+		} else {
+			rc = devm_request_threaded_irq(&client->dev,
+						chip->usb_id_irq, NULL,
+						smb1360_usb_id_irq_handler,
+						IRQF_ONESHOT
+						| IRQF_TRIGGER_FALLING
+						| IRQF_TRIGGER_RISING,
+						"smb1360_usb_id_irq", chip);
+			if (rc < 0) {
+				dev_err(&client->dev,
+					"usb-id request_irq for irq=%d  failed rc = %d\n",
+					chip->usb_id_irq, rc);
+				goto unregister_batt_psy;
+			}
+			enable_irq_wake(chip->usb_id_irq);
+		}
+	}
 	chip->debug_root = debugfs_create_dir("smb1360", NULL);
 	if (!chip->debug_root)
 		dev_err(chip->dev, "Couldn't create debug dir\n");
@@ -5201,7 +5277,8 @@
 unregister_batt_psy:
 	power_supply_unregister(chip->batt_psy);
 fail_hw_init:
-	regulator_unregister(chip->otg_vreg.rdev);
+	if (chip->otg_vreg.rdev)
+		regulator_unregister(chip->otg_vreg.rdev);
 destroy_mutex:
 	power_supply_unregister(chip->usb_psy);
 	wakeup_source_trash(&chip->smb1360_ws.source);
@@ -5218,8 +5295,9 @@
 static int smb1360_remove(struct i2c_client *client)
 {
 	struct smb1360_chip *chip = i2c_get_clientdata(client);
+	if (chip->otg_vreg.rdev)
+		regulator_unregister(chip->otg_vreg.rdev);
 
-	regulator_unregister(chip->otg_vreg.rdev);
 	power_supply_unregister(chip->usb_psy);
 	power_supply_unregister(chip->batt_psy);
 	wakeup_source_trash(&chip->smb1360_ws.source);
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 6f13635..a68f2b0 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019 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
@@ -774,6 +774,9 @@
 
 	cancel_delayed_work_sync(&chg->pl_enable_work);
 
+	if (chg->wa_flags & CHG_TERMINATION_WA)
+		alarm_cancel(&chg->chg_termination_alarm);
+
 	if (chg->wa_flags & BOOST_BACK_WA) {
 		data = chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data;
 		if (data) {
@@ -793,6 +796,7 @@
 	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
 			is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
+	vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
 
 	/* reconfigure allowed voltage for HVDCP */
 	rc = smblib_set_adapter_allowance(chg,
@@ -1482,6 +1486,16 @@
 		break;
 	}
 
+	/*
+	 * If charge termination WA is active and has suspended charging, then
+	 * continue reporting charging status as FULL.
+	 */
+	if (is_client_vote_enabled(chg->usb_icl_votable,
+						CHG_TERMINATION_VOTER)) {
+		val->intval = POWER_SUPPLY_STATUS_FULL;
+		return 0;
+	}
+
 	if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
 		return 0;
 
@@ -1991,6 +2005,12 @@
 		return rc;
 	}
 
+	if (is_client_vote_enabled(chg->usb_icl_votable,
+					CHG_TERMINATION_VOTER)) {
+		rc = smblib_get_prop_usb_present(chg, val);
+		return rc;
+	}
+
 	rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
@@ -2760,6 +2780,38 @@
 	return IRQ_HANDLED;
 }
 
+#define CHG_TERM_WA_ENTRY_DELAY_MS		300000		/* 5 min */
+#define CHG_TERM_WA_EXIT_DELAY_MS		60000		/* 1 min */
+static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
+{
+	union power_supply_propval pval = {0, };
+	int rc = 0;
+
+	rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read SOC value, rc=%d\n", rc);
+		return;
+	}
+
+	/*
+	 * Post charge termination, switch to BSM mode triggers the risk of
+	 * over charging as BATFET opening may take some time post the necessity
+	 * of staying in supplemental mode, leading to unintended charging of
+	 * battery. Trigger the charge termination WA once charging is completed
+	 * to prevent overcharing.
+	 */
+	if ((batt_status == TERMINATE_CHARGE) && (pval.intval == 100)) {
+		alarm_start_relative(&chg->chg_termination_alarm,
+			ms_to_ktime(CHG_TERM_WA_ENTRY_DELAY_MS));
+	} else if (pval.intval < 100) {
+		/*
+		 * Reset CC_SOC reference value for charge termination WA once
+		 * we exit the TERMINATE_CHARGE state and soc drops below 100%
+		 */
+		chg->cc_soc_ref = 0;
+	}
+}
+
 irqreturn_t chg_state_change_irq_handler(int irq, void *data)
 {
 	struct smb_irq_data *irq_data = data;
@@ -2777,6 +2829,10 @@
 	}
 
 	stat = stat & BATTERY_CHARGER_STATUS_MASK;
+
+	if (chg->wa_flags & CHG_TERMINATION_WA)
+		smblib_eval_chg_termination(chg, stat);
+
 	power_supply_changed(chg->batt_psy);
 	return IRQ_HANDLED;
 }
@@ -3469,6 +3525,9 @@
 
 	cancel_delayed_work_sync(&chg->pl_enable_work);
 
+	if (chg->wa_flags & CHG_TERMINATION_WA)
+		alarm_cancel(&chg->chg_termination_alarm);
+
 	/* reset input current limit voters */
 	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
 			is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
@@ -3479,6 +3538,7 @@
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
 	vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
 	vote(chg->usb_icl_votable, CTM_VOTER, false, 0);
+	vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
 
 	/* reset usb irq voters */
 	vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);
@@ -3996,6 +4056,12 @@
 	u8 stat;
 
 	/*
+	 * Hold awake votable to prevent pm_relax being called prior to
+	 * completion of this work.
+	 */
+	vote(chg->awake_votable, MOISTURE_VOTER, true, 0);
+
+	/*
 	 * Disable 1% duty cycle on CC_ID pin and enable uUSB factory mode
 	 * detection to track any change on RID, as interrupts are disable.
 	 */
@@ -4057,6 +4123,7 @@
 	}
 
 out:
+	vote(chg->awake_votable, MOISTURE_VOTER, false, 0);
 	pm_relax(chg->dev);
 }
 
@@ -4076,6 +4143,93 @@
 	return ALARMTIMER_NORESTART;
 }
 
+static void smblib_chg_termination_work(struct work_struct *work)
+{
+	struct smb_charger *chg = container_of(work, struct smb_charger,
+						chg_termination_work);
+	union power_supply_propval pval;
+	int rc, delay = CHG_TERM_WA_ENTRY_DELAY_MS;
+
+	/*
+	 * Hold awake votable to prevent pm_relax being called prior to
+	 * completion of this work.
+	 */
+	vote(chg->awake_votable, CHG_TERMINATION_VOTER, true, 0);
+
+	rc = smblib_get_prop_usb_present(chg, &pval);
+	if (rc < 0 || !pval.intval)
+		goto out;
+
+	rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval);
+	if (rc < 0 || (pval.intval < 100)) {
+		vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
+		goto out;
+	}
+
+	rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CHARGE_FULL,
+					&pval);
+	if (rc < 0)
+		goto out;
+
+	/*
+	 * On change in the value of learned capacity, re-initialize the
+	 * reference cc_soc value due to change in cc_soc characteristic value
+	 * at full capacity. Also, in case cc_soc_ref value is reset,
+	 * re-initialize it.
+	 */
+	if ((pval.intval != chg->charge_full_cc) || !chg->cc_soc_ref) {
+		chg->charge_full_cc = pval.intval;
+		rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CC_SOC,
+					&pval);
+		if (rc < 0)
+			goto out;
+
+		chg->cc_soc_ref = pval.intval;
+	} else {
+		rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CC_SOC,
+					&pval);
+		if (rc < 0)
+			goto out;
+	}
+
+	/*
+	 * Suspend/Unsuspend USB input to keep cc_soc within the 0.5% to 0.75%
+	 * overshoot range of the cc_soc value at termination, to prevent
+	 * overcharging.
+	 */
+	if (pval.intval < DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10050, 10000)) {
+		vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
+		delay = CHG_TERM_WA_ENTRY_DELAY_MS;
+	} else if (pval.intval > DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10075,
+								10000)) {
+		vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, true, 0);
+		delay = CHG_TERM_WA_EXIT_DELAY_MS;
+	}
+
+	smblib_dbg(chg, PR_MISC, "Chg Term WA readings: cc_soc: %d, cc_soc_ref: %d, delay: %d\n",
+			pval.intval, chg->cc_soc_ref, delay);
+	alarm_start_relative(&chg->chg_termination_alarm, ms_to_ktime(delay));
+out:
+	vote(chg->awake_votable, CHG_TERMINATION_VOTER, false, 0);
+	pm_relax(chg->dev);
+}
+
+static enum alarmtimer_restart chg_termination_alarm_cb(struct alarm *alarm,
+							ktime_t now)
+{
+	struct smb_charger *chg = container_of(alarm, struct smb_charger,
+						chg_termination_alarm);
+
+	smblib_dbg(chg, PR_MISC, "Charge termination WA alarm triggered %lld\n",
+			ktime_to_ms(now));
+
+	/* Atomic context, cannot use voter */
+	pm_stay_awake(chg->dev);
+	schedule_work(&chg->chg_termination_work);
+
+	return ALARMTIMER_NORESTART;
+}
+
 #define JEITA_SOFT			0
 #define JEITA_HARD			1
 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds,
@@ -4288,6 +4442,19 @@
 	INIT_DELAYED_WORK(&chg->bb_removal_work, smblib_bb_removal_work);
 	INIT_DELAYED_WORK(&chg->usbov_dbc_work, smblib_usbov_dbc_work);
 
+	if (chg->wa_flags & CHG_TERMINATION_WA) {
+		INIT_WORK(&chg->chg_termination_work,
+					smblib_chg_termination_work);
+
+		if (alarmtimer_get_rtcdev()) {
+			alarm_init(&chg->chg_termination_alarm, ALARM_BOOTTIME,
+						chg_termination_alarm_cb);
+		} else {
+			smblib_err(chg, "Couldn't get rtc device\n");
+			return -ENODEV;
+		}
+	}
+
 	if (chg->moisture_protection_enabled &&
 				(chg->wa_flags & MOISTURE_PROTECTION_WA)) {
 		INIT_WORK(&chg->moisture_protection_work,
@@ -4368,6 +4535,10 @@
 			alarm_cancel(&chg->moisture_protection_alarm);
 			cancel_work_sync(&chg->moisture_protection_work);
 		}
+		if (chg->wa_flags & CHG_TERMINATION_WA) {
+			alarm_cancel(&chg->chg_termination_alarm);
+			cancel_work_sync(&chg->chg_termination_work);
+		}
 		cancel_work_sync(&chg->bms_update_work);
 		cancel_work_sync(&chg->jeita_update_work);
 		cancel_work_sync(&chg->pl_update_work);
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 1bba206..64b640f 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -72,6 +72,7 @@
 #define MOISTURE_VOTER			"MOISTURE_VOTER"
 #define USBOV_DBC_VOTER			"USBOV_DBC_VOTER"
 #define FCC_STEPPER_VOTER		"FCC_STEPPER_VOTER"
+#define CHG_TERMINATION_VOTER		"CHG_TERMINATION_VOTER"
 
 #define BOOST_BACK_STORM_COUNT	3
 #define WEAK_CHG_STORM_COUNT	8
@@ -104,6 +105,7 @@
 	WEAK_ADAPTER_WA			= BIT(1),
 	MOISTURE_PROTECTION_WA		= BIT(2),
 	USBIN_OV_WA			= BIT(3),
+	CHG_TERMINATION_WA		= BIT(4),
 };
 
 enum {
@@ -345,6 +347,7 @@
 	struct work_struct	pl_update_work;
 	struct work_struct	jeita_update_work;
 	struct work_struct	moisture_protection_work;
+	struct work_struct	chg_termination_work;
 	struct delayed_work	ps_change_timeout_work;
 	struct delayed_work	clear_hdc_work;
 	struct delayed_work	icl_change_work;
@@ -355,6 +358,7 @@
 
 	/* alarm */
 	struct alarm		moisture_protection_alarm;
+	struct alarm		chg_termination_alarm;
 
 	/* pd */
 	int			voltage_min_uv;
@@ -407,6 +411,8 @@
 	bool			moisture_present;
 	bool			moisture_protection_enabled;
 	bool			fcc_stepper_enable;
+	int			charge_full_cc;
+	int			cc_soc_ref;
 
 	/* workaround flag */
 	u32			wa_flags;
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 0fd7802..744e35a 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -114,6 +114,10 @@
 #define PFM_CURRENT_SHIFT		2
 
 #define LCDB_PWRUP_PWRDN_CTL_REG	0x66
+#define PWRUP_DELAY_MASK		GENAMSK(3, 2)
+#define PWRDN_DELAY_MASK		GENMASK(1, 0)
+#define PWRDN_DELAY_MIN_MS		0
+#define PWRDN_DELAY_MAX_MS		8
 
 /* LDO */
 #define LCDB_LDO_OUTPUT_VOLTAGE_REG	0x71
@@ -126,6 +130,10 @@
 #define LDO_DIS_PULLDOWN_BIT		BIT(1)
 #define LDO_PD_STRENGTH_BIT		BIT(0)
 
+#define LCDB_LDO_FORCE_PD_CTL_REG	0x79
+#define LDO_FORCE_PD_EN_BIT		BIT(0)
+#define LDO_FORCE_PD_MODE		BIT(7)
+
 #define LCDB_LDO_ILIM_CTL1_REG		0x7B
 #define EN_LDO_ILIM_BIT			BIT(7)
 #define SET_LDO_ILIM_MASK		GENMASK(2, 0)
@@ -223,6 +231,7 @@
 	u32				base;
 	u32				wa_flags;
 	int				sc_irq;
+	int				pwrdn_delay_ms;
 
 	/* TTW params */
 	bool				ttw_enable;
@@ -297,6 +306,7 @@
 
 enum lcdb_wa_flags {
 	NCP_SCP_DISABLE_WA = BIT(0),
+	FORCE_PD_ENABLE_WA = BIT(1),
 };
 
 static u32 soft_start_us[] = {
@@ -320,6 +330,13 @@
 	810,
 };
 
+static const u32 pwrup_pwrdn_ms[] = {
+	0,
+	1,
+	4,
+	8,
+};
+
 #define SETTING(_id, _sec_access, _valid)	\
 	[_id] = {				\
 		.address = _id##_REG,		\
@@ -922,6 +939,18 @@
 		return 0;
 	}
 
+	if (lcdb->wa_flags & FORCE_PD_ENABLE_WA) {
+		/*
+		 * force pull-down to enable quick discharge after
+		 * turning off
+		 */
+		val = LDO_FORCE_PD_EN_BIT | LDO_FORCE_PD_MODE;
+		rc = qpnp_lcdb_write(lcdb, lcdb->base +
+				     LCDB_LDO_FORCE_PD_CTL_REG, &val, 1);
+		if (rc < 0)
+			return rc;
+	}
+
 	val = 0;
 	rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
 							&val, 1);
@@ -930,6 +959,17 @@
 	else
 		lcdb->lcdb_enabled = false;
 
+	if (lcdb->wa_flags & FORCE_PD_ENABLE_WA) {
+		/* wait for 10 msec after module disable for LDO to discharge */
+		usleep_range(10000, 11000);
+
+		val = 0;
+		rc = qpnp_lcdb_write(lcdb, lcdb->base +
+				     LCDB_LDO_FORCE_PD_CTL_REG, &val, 1);
+		if (rc < 0)
+			return rc;
+	}
+
 	return rc;
 }
 
@@ -2052,6 +2092,10 @@
 		if (lcdb->pmic_rev_id->rev4 < PM660L_V2P0_REV4)
 			lcdb->wa_flags |= NCP_SCP_DISABLE_WA;
 		break;
+	case PMI632_SUBTYPE:
+	case PM855L_SUBTYPE:
+		lcdb->wa_flags |= FORCE_PD_ENABLE_WA;
+		break;
 	default:
 		break;
 	}
@@ -2066,6 +2110,15 @@
 
 	qpnp_lcdb_pmic_config(lcdb);
 
+	if (lcdb->pwrdn_delay_ms != -EINVAL) {
+		rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
+					    LCDB_PWRUP_PWRDN_CTL_REG,
+					    PWRDN_DELAY_MASK,
+					    lcdb->pwrdn_delay_ms);
+		if (rc < 0)
+			return rc;
+	}
+
 	rc = qpnp_lcdb_init_bst(lcdb);
 	if (rc < 0) {
 		pr_err("Failed to initialize BOOST rc=%d\n", rc);
@@ -2124,7 +2177,8 @@
 
 static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
 {
-	int rc = 0;
+	int rc = 0, i = 0;
+	u32 tmp;
 	const char *label;
 	struct device_node *revid_dev_node, *temp, *node = lcdb->dev->of_node;
 
@@ -2189,7 +2243,24 @@
 	lcdb->voltage_step_ramp =
 			of_property_read_bool(node, "qcom,voltage-step-ramp");
 
-	return rc;
+	lcdb->pwrdn_delay_ms = -EINVAL;
+	rc = of_property_read_u32(node, "qcom,pwrdn-delay-ms", &tmp);
+	if (!rc) {
+		if (!is_between(tmp, PWRDN_DELAY_MIN_MS, PWRDN_DELAY_MAX_MS)) {
+			pr_err("Invalid PWRDN_DLY val %d (min=%d max=%d)\n",
+				tmp, PWRDN_DELAY_MIN_MS, PWRDN_DELAY_MAX_MS);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(pwrup_pwrdn_ms); i++) {
+			if (tmp == pwrup_pwrdn_ms[i]) {
+				lcdb->pwrdn_delay_ms = i;
+				break;
+			}
+		}
+	}
+
+	return 0;
 }
 
 static ssize_t qpnp_lcdb_irq_control(struct class *c,
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index d4fe6ee..a2b7257 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, 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
@@ -226,14 +226,17 @@
 	}
 
 	qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
-	ice_workqueue = alloc_workqueue("ice-set-key",
-			WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
 	if (!ice_workqueue) {
-		dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
+		ice_workqueue = alloc_workqueue("ice-set-key",
+			WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+		if (!ice_workqueue) {
+			dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
 			__func__);
-		goto out;
+			err = -ENOMEM;
+			goto out;
+		}
+		INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
 	}
-	INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
 
 out:
 	return err;
@@ -286,6 +289,17 @@
 			 * propagate so it will be re-queued.
 			 */
 			if (err == -EAGAIN) {
+				if (!ice_workqueue) {
+					spin_unlock_irqrestore(
+					&qcom_host->ice_work_lock,
+					flags);
+
+					dev_err(qcom_host->hba->dev,
+						"%s: error %d workqueue NULL\n",
+						__func__, err);
+					return -EINVAL;
+				}
+
 				dev_dbg(qcom_host->hba->dev,
 					"%s: scheduling task for ice setup\n",
 					__func__);
@@ -405,6 +419,16 @@
 			 * propagate so it will be re-queued.
 			 */
 			if (err == -EAGAIN) {
+				if (!ice_workqueue) {
+					spin_unlock_irqrestore(
+					&qcom_host->ice_work_lock,
+					flags);
+
+					dev_err(qcom_host->hba->dev,
+						"%s: error %d workqueue NULL\n",
+						__func__, err);
+					return -EINVAL;
+				}
 
 				dev_dbg(qcom_host->hba->dev,
 					"%s: scheduling task for ice setup\n",
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index acd5c85..e05fa35 100755
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
  *
  * Authors:
  *	Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -3384,7 +3384,7 @@
 		ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
 	}
 
-	if (err)
+	if (err && err != -EAGAIN)
 		ufsdbg_set_err_state(hba);
 
 	return err;
@@ -3445,18 +3445,6 @@
 	int tag;
 	struct completion wait;
 	unsigned long flags;
-	bool has_read_lock = false;
-
-	/*
-	 * May get invoked from shutdown and IOCTL contexts.
-	 * In shutdown context, it comes in with lock acquired.
-	 * In error recovery context, it may come with lock acquired.
-	 */
-
-	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
-		down_read(&hba->lock);
-		has_read_lock = true;
-	}
 
 	/*
 	 * Get free slot, sleep if slots are unavailable.
@@ -3489,8 +3477,6 @@
 out_put_tag:
 	ufshcd_put_dev_cmd_tag(hba, tag);
 	wake_up(&hba->dev_cmd.tag_wq);
-	if (has_read_lock)
-		up_read(&hba->lock);
 	return err;
 }
 
@@ -3565,10 +3551,15 @@
 	struct ufs_query_res *response = NULL;
 	int err, index = 0, selector = 0;
 	int timeout = QUERY_REQ_TIMEOUT;
+	bool has_read_lock = false;
 
 	BUG_ON(!hba);
 
 	ufshcd_hold_all(hba);
+	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+		down_read(&hba->lock);
+		has_read_lock = true;
+	}
 	mutex_lock(&hba->dev_cmd.lock);
 	ufshcd_init_query(hba, &request, &response, opcode, idn, index,
 			selector);
@@ -3612,6 +3603,8 @@
 
 out_unlock:
 	mutex_unlock(&hba->dev_cmd.lock);
+	if (has_read_lock)
+		up_read(&hba->lock);
 	ufshcd_release_all(hba);
 	return err;
 }
@@ -3634,6 +3627,7 @@
 	struct ufs_query_req *request = NULL;
 	struct ufs_query_res *response = NULL;
 	int err;
+	bool has_read_lock = false;
 
 	BUG_ON(!hba);
 
@@ -3645,6 +3639,16 @@
 		goto out;
 	}
 
+	/*
+	 * May get invoked from shutdown and IOCTL contexts.
+	 * In shutdown context, it comes in with lock acquired.
+	 * In error recovery context, it may come with lock acquired.
+	 */
+
+	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+		down_read(&hba->lock);
+		has_read_lock = true;
+	}
 	mutex_lock(&hba->dev_cmd.lock);
 	ufshcd_init_query(hba, &request, &response, opcode, idn, index,
 			selector);
@@ -3677,6 +3681,8 @@
 
 out_unlock:
 	mutex_unlock(&hba->dev_cmd.lock);
+	if (has_read_lock)
+		up_read(&hba->lock);
 out:
 	ufshcd_release_all(hba);
 	return err;
@@ -3727,6 +3733,7 @@
 	struct ufs_query_req *request = NULL;
 	struct ufs_query_res *response = NULL;
 	int err;
+	bool has_read_lock = false;
 
 	BUG_ON(!hba);
 
@@ -3745,6 +3752,10 @@
 		goto out;
 	}
 
+	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+		down_read(&hba->lock);
+		has_read_lock = true;
+	}
 	mutex_lock(&hba->dev_cmd.lock);
 	ufshcd_init_query(hba, &request, &response, opcode, idn, index,
 			selector);
@@ -3780,6 +3791,9 @@
 
 out_unlock:
 	mutex_unlock(&hba->dev_cmd.lock);
+	if (has_read_lock)
+		up_read(&hba->lock);
+
 out:
 	ufshcd_release_all(hba);
 	return err;
@@ -5301,8 +5315,13 @@
 {
 	int err = 0;
 	int retries;
+	bool has_read_lock = false;
 
 	ufshcd_hold_all(hba);
+	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+		down_read(&hba->lock);
+		has_read_lock = true;
+	}
 	mutex_lock(&hba->dev_cmd.lock);
 	for (retries = NOP_OUT_RETRIES; retries > 0; retries--) {
 		err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_NOP,
@@ -5314,6 +5333,8 @@
 		dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
 	}
 	mutex_unlock(&hba->dev_cmd.lock);
+	if (has_read_lock)
+		up_read(&hba->lock);
 	ufshcd_release_all(hba);
 
 	if (err)
@@ -10251,12 +10272,9 @@
 		 * e.g. link_recovery. Hence, release the rw_sem
 		 * before hibern8.
 		 */
-		up_write(&hba->lock);
 		ret = ufshcd_uic_hibern8_enter(hba);
-		down_write(&hba->lock);
 		if (ret)
-			/* link will be bad state so no need to scale_up_gear */
-			return ret;
+			goto scale_up_gear;
 		ufshcd_custom_cmd_log(hba, "Hibern8-entered");
 	}
 
@@ -10268,8 +10286,7 @@
 	if (ufshcd_is_auto_hibern8_supported(hba)) {
 		ret = ufshcd_uic_hibern8_exit(hba);
 		if (ret)
-			/* link will be bad state so no need to scale_up_gear */
-			return ret;
+			goto scale_up_gear;
 		ufshcd_custom_cmd_log(hba, "Hibern8-Exited");
 	}
 
diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c
index b13f06d..024b491 100644
--- a/drivers/soc/qcom/bgcom_spi.c
+++ b/drivers/soc/qcom/bgcom_spi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -106,6 +106,7 @@
 static void send_input_events(struct work_struct *work);
 static struct list_head cb_head = LIST_HEAD_INIT(cb_head);
 static struct list_head pr_lst_hd = LIST_HEAD_INIT(pr_lst_hd);
+static DEFINE_SPINLOCK(lst_setup_lock);
 static enum bgcom_spi_state spi_state;
 
 
@@ -148,7 +149,9 @@
 		evnt = node->evnt;
 		bgrsb_send_input(evnt);
 		kfree(evnt);
+		spin_lock(&lst_setup_lock);
 		list_del(&node->list);
+		spin_unlock(&lst_setup_lock);
 		kfree(node);
 	}
 }
@@ -323,8 +326,9 @@
 
 			data_list = kmalloc(sizeof(*data_list), GFP_KERNEL);
 			data_list->evnt = evnt;
+			spin_lock(&lst_setup_lock);
 			list_add_tail(&data_list->list, &pr_lst_hd);
-
+			spin_unlock(&lst_setup_lock);
 		} else if (event_id == 0x0001) {
 			evnt_data = kmalloc(p_len, GFP_KERNEL);
 			if (evnt_data != NULL) {
@@ -821,6 +825,19 @@
 		return -ECANCELED;
 
 	cntx = (struct bg_context *)handle;
+
+	/* if client is outside bgcom scope and
+	 * handle is provided before BGCOM probed
+	 */
+	if (cntx->state == BGCOM_PROB_WAIT) {
+		pr_info("handle is provided before BGCOM probed\n");
+		if (!is_bgcom_ready())
+			return -EAGAIN;
+		cntx->bg_spi = container_of(bg_com_drv,
+						struct bg_spi_priv, lhandle);
+		cntx->state = BGCOM_PROB_SUCCESS;
+	}
+
 	bg_spi = cntx->bg_spi;
 
 	mutex_lock(&bg_resume_mutex);
@@ -1006,7 +1023,7 @@
 
 	bg_irq = gpio_to_irq(irq_gpio);
 	ret = request_threaded_irq(bg_irq, NULL, bg_irq_tasklet_hndlr,
-		IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "qcom,bg_spi", bg_spi);
+		IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "qcom-bg_spi", bg_spi);
 
 	if (ret)
 		goto err_ret;
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index 5640666..f131c79 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, 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
@@ -483,6 +483,8 @@
 	uint32_t fifo_size = einfo->rx_fifo_size;
 	uint32_t n;
 
+	if (read_index >= fifo_size || write_index >= fifo_size)
+		return 0;
 	while (len) {
 		ptr = einfo->rx_fifo + read_index;
 		if (read_index <= write_index)
@@ -529,6 +531,8 @@
 	uint32_t fifo_size = einfo->tx_fifo_size;
 	uint32_t n;
 
+	if (read_index >= fifo_size || *write_index >= fifo_size)
+		return 0;
 	while (len) {
 		ptr = einfo->tx_fifo + *write_index;
 		if (*write_index < read_index) {
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index a7d262b..165a1749 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -76,6 +76,8 @@
 
 #define ICNSS_MAX_PROBE_CNT		2
 
+#define PROBE_TIMEOUT			5000
+
 #define icnss_ipc_log_string(_x...) do {				\
 	if (icnss_ipc_log_context)					\
 		ipc_log_string(icnss_ipc_log_context, _x);		\
@@ -286,6 +288,7 @@
 	ICNSS_DRIVER_UNLOADING,
 	ICNSS_REJUVENATE,
 	ICNSS_MODE_ON,
+	ICNSS_BLOCK_SHUTDOWN,
 };
 
 struct ce_irq_list {
@@ -475,6 +478,7 @@
 	struct mutex dev_lock;
 	uint32_t fw_error_fatal_irq;
 	uint32_t fw_early_crash_irq;
+	struct completion unblock_shutdown;
 } *penv;
 
 #ifdef CONFIG_ICNSS_DEBUG
@@ -1164,6 +1168,21 @@
 }
 EXPORT_SYMBOL(icnss_is_fw_ready);
 
+void icnss_block_shutdown(bool status)
+{
+	if (!penv)
+		return;
+
+	if (status) {
+		set_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
+		reinit_completion(&penv->unblock_shutdown);
+	} else {
+		clear_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
+		complete(&penv->unblock_shutdown);
+	}
+}
+EXPORT_SYMBOL(icnss_block_shutdown);
+
 bool icnss_is_fw_down(void)
 {
 	if (!penv)
@@ -2257,6 +2276,7 @@
 
 	icnss_hw_power_on(priv);
 
+	icnss_block_shutdown(true);
 	while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
 		ret = priv->ops->probe(&priv->pdev->dev);
 		probe_cnt++;
@@ -2266,9 +2286,11 @@
 	if (ret < 0) {
 		icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
 			     ret, priv->state, probe_cnt);
+		icnss_block_shutdown(false);
 		goto out;
 	}
 
+	icnss_block_shutdown(false);
 	set_bit(ICNSS_DRIVER_PROBED, &priv->state);
 
 	return 0;
@@ -2407,6 +2429,7 @@
 	if (ret)
 		goto out;
 
+	icnss_block_shutdown(true);
 	while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
 		ret = penv->ops->probe(&penv->pdev->dev);
 		probe_cnt++;
@@ -2416,9 +2439,11 @@
 	if (ret) {
 		icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
 			     ret, penv->state, probe_cnt);
+		icnss_block_shutdown(false);
 		goto power_off;
 	}
 
+	icnss_block_shutdown(false);
 	set_bit(ICNSS_DRIVER_PROBED, &penv->state);
 
 	return 0;
@@ -2498,7 +2523,8 @@
 		goto out;
 	}
 
-	icnss_fw_crashed(priv, event_data);
+	if (!test_bit(ICNSS_PD_RESTART, &priv->state))
+		icnss_fw_crashed(priv, event_data);
 
 out:
 	kfree(data);
@@ -2685,6 +2711,13 @@
 	if (code != SUBSYS_BEFORE_SHUTDOWN)
 		return NOTIFY_OK;
 
+	if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
+	    test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
+		if (!wait_for_completion_timeout(&priv->unblock_shutdown,
+						 PROBE_TIMEOUT))
+			icnss_pr_err("wlan driver probe timeout\n");
+	}
+
 	if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) {
 		set_bit(ICNSS_FW_DOWN, &priv->state);
 		icnss_ignore_qmi_timeout(true);
@@ -4050,6 +4083,9 @@
 			continue;
 		case ICNSS_MODE_ON:
 			seq_puts(s, "MODE ON DONE");
+			continue;
+		case ICNSS_BLOCK_SHUTDOWN:
+			seq_puts(s, "BLOCK SHUTDOWN");
 		}
 
 		seq_printf(s, "UNKNOWN-%d", i);
@@ -4721,6 +4757,8 @@
 
 	penv = priv;
 
+	init_completion(&priv->unblock_shutdown);
+
 	icnss_pr_info("Platform driver probed successfully\n");
 
 	return 0;
@@ -4743,6 +4781,8 @@
 
 	icnss_debugfs_destroy(penv);
 
+	complete_all(&penv->unblock_shutdown);
+
 	icnss_modem_ssr_unregister_notifier(penv);
 
 	destroy_ramdump_device(penv->msa0_dump_dev);
diff --git a/drivers/soc/qcom/wcnss/wcnss_vreg.c b/drivers/soc/qcom/wcnss/wcnss_vreg.c
index 1e61250..476ff60 100644
--- a/drivers/soc/qcom/wcnss/wcnss_vreg.c
+++ b/drivers/soc/qcom/wcnss/wcnss_vreg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2018-2019 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
@@ -38,6 +38,7 @@
 
 #define PRONTO_IRIS_REG_READ_OFFSET       0x1134
 #define PRONTO_IRIS_REG_CHIP_ID           0x04
+#define PRONTO_IRIS_REG_CHIP_ID_MASK      0xffff
 /* IRIS card chip ID's */
 #define WCN3660       0x0200
 #define WCN3660A      0x0300
@@ -46,6 +47,7 @@
 #define WCN3620A      0x5112
 #define WCN3610       0x9101
 #define WCN3610V1     0x9110
+#define WCN3615       0x8110
 
 #define WCNSS_PMU_CFG_IRIS_XO_CFG          BIT(3)
 #define WCNSS_PMU_CFG_IRIS_XO_EN           BIT(4)
@@ -107,7 +109,8 @@
 enum {
 	IRIS_3660, /* also 3660A and 3680 */
 	IRIS_3620,
-	IRIS_3610
+	IRIS_3610,
+	IRIS_3615
 };
 
 int xo_auto_detect(u32 reg)
@@ -124,6 +127,9 @@
 	case IRIS_3610:
 		return WCNSS_XO_19MHZ;
 
+	case IRIS_3615:
+		return WCNSS_XO_19MHZ;
+
 	default:
 		return WCNSS_XO_INVALID;
 	}
@@ -132,13 +138,13 @@
 int wcnss_get_iris_name(char *iris_name)
 {
 	struct wcnss_wlan_config *cfg = NULL;
-	int iris_id;
+	u32  iris_id;
 
 	cfg = wcnss_get_wlan_config();
 
 	if (cfg) {
 		iris_id = cfg->iris_id;
-		iris_id = iris_id >> 16;
+		iris_id = PRONTO_IRIS_REG_CHIP_ID_MASK & (iris_id >> 16);
 	} else {
 		return 1;
 	}
@@ -165,6 +171,9 @@
 	case WCN3610V1:
 		memcpy(iris_name, "WCN3610V1", sizeof("WCN3610V1"));
 		break;
+	case WCN3615:
+		memcpy(iris_name, "WCN3615", sizeof("WCN3615"));
+		break;
 	default:
 		return 1;
 	}
@@ -175,9 +184,9 @@
 
 int validate_iris_chip_id(u32 reg)
 {
-	int iris_id;
+	u32 iris_id;
 
-	iris_id = reg >> 16;
+	iris_id = PRONTO_IRIS_REG_CHIP_ID_MASK & (reg >> 16);
 
 	switch (iris_id) {
 	case WCN3660:
@@ -187,6 +196,7 @@
 	case WCN3620A:
 	case WCN3610:
 	case WCN3610V1:
+	case WCN3615:
 		return 0;
 	default:
 		return 1;
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index fe811d7..2f1258a 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -578,12 +578,8 @@
 }
 EXPORT_SYMBOL(of_thermal_aggregate_trip);
 
-/*
- * of_thermal_handle_trip - Handle thermal trip from sensors
- *
- * @tz: pointer to the primary thermal zone.
- */
-void of_thermal_handle_trip(struct thermal_zone_device *tz)
+static void handle_thermal_trip(struct thermal_zone_device *tz,
+		bool temp_valid, int trip_temp)
 {
 	struct thermal_zone_device *zone;
 	struct __thermal_zone *data = tz->devdata;
@@ -594,9 +590,38 @@
 		zone = data->tzd;
 		if (data->mode == THERMAL_DEVICE_DISABLED)
 			continue;
-		thermal_zone_device_update(zone, THERMAL_EVENT_UNSPECIFIED);
+		if (!temp_valid) {
+			thermal_zone_device_update(zone,
+				THERMAL_EVENT_UNSPECIFIED);
+		} else {
+			thermal_zone_device_update_temp(zone,
+				THERMAL_EVENT_UNSPECIFIED, trip_temp);
+		}
 	}
 }
+
+/*
+ * of_thermal_handle_trip_temp - Handle thermal trip from sensors
+ *
+ * @tz: pointer to the primary thermal zone.
+ * @trip_temp: The temperature
+ */
+void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
+		int trip_temp)
+{
+	return handle_thermal_trip(tz, true, trip_temp);
+}
+EXPORT_SYMBOL(of_thermal_handle_trip_temp);
+
+/*
+ * of_thermal_handle_trip - Handle thermal trip from sensors
+ *
+ * @tz: pointer to the primary thermal zone.
+ */
+void of_thermal_handle_trip(struct thermal_zone_device *tz)
+{
+	return handle_thermal_trip(tz, false, 0);
+}
 EXPORT_SYMBOL(of_thermal_handle_trip);
 
 static struct thermal_zone_device_ops of_thermal_ops = {
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index cc3af57..4309c9a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -458,7 +458,7 @@
 	}
 }
 
-void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 {
 	enum thermal_trip_type type;
 
@@ -576,19 +576,8 @@
 }
 EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
 
-static void update_temperature(struct thermal_zone_device *tz)
+static void store_temperature(struct thermal_zone_device *tz, int temp)
 {
-	int temp, ret;
-
-	ret = thermal_zone_get_temp(tz, &temp);
-	if (ret) {
-		if (ret != -EAGAIN)
-			dev_warn(&tz->device,
-				 "failed to read out thermal zone (%d)\n",
-				 ret);
-		return;
-	}
-
 	mutex_lock(&tz->lock);
 	tz->last_temperature = tz->temperature;
 	tz->temperature = temp;
@@ -604,6 +593,21 @@
 			tz->last_temperature, tz->temperature);
 }
 
+static void update_temperature(struct thermal_zone_device *tz)
+{
+	int temp, ret;
+
+	ret = thermal_zone_get_temp(tz, &temp);
+	if (ret) {
+		if (ret != -EAGAIN)
+			dev_warn(&tz->device,
+				 "failed to read out thermal zone (%d)\n",
+				 ret);
+		return;
+	}
+	store_temperature(tz, temp);
+}
+
 static void thermal_zone_device_reset(struct thermal_zone_device *tz)
 {
 	struct thermal_instance *pos;
@@ -614,6 +618,26 @@
 		pos->initialized = false;
 }
 
+void thermal_zone_device_update_temp(struct thermal_zone_device *tz,
+				enum thermal_notify_event event, int temp)
+{
+	int count;
+
+	if (atomic_read(&in_suspend))
+		return;
+
+	trace_thermal_device_update(tz, event);
+	store_temperature(tz, temp);
+
+	thermal_zone_set_trips(tz);
+
+	tz->notify_event = event;
+
+	for (count = 0; count < tz->trips; count++)
+		handle_thermal_trip(tz, count);
+}
+EXPORT_SYMBOL(thermal_zone_device_update_temp);
+
 void thermal_zone_device_update(struct thermal_zone_device *tz,
 				enum thermal_notify_event event)
 {
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 567f630..5a0b77b 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -60,7 +60,6 @@
 
 int thermal_register_governor(struct thermal_governor *);
 void thermal_unregister_governor(struct thermal_governor *);
-void handle_thermal_trip(struct thermal_zone_device *tz, int trip);
 
 #ifdef CONFIG_THERMAL_GOV_STEP_WISE
 int thermal_gov_step_wise_register(void);
@@ -122,6 +121,8 @@
 			      enum thermal_trip_type type,
 			      int *low, int *high);
 void of_thermal_handle_trip(struct thermal_zone_device *tz);
+void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
+					int trip_temp);
 #else
 static inline int of_parse_thermal_zones(void) { return 0; }
 static inline void of_thermal_destroy_zones(void) { }
@@ -148,6 +149,10 @@
 static inline
 void of_thermal_handle_trip(struct thermal_zone_device *tz)
 { }
+static inline
+void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
+					int trip_temp)
+{ }
 #endif
 
 #endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c
index 0dc375f..3c531a7 100644
--- a/drivers/thermal/tsens2xxx.c
+++ b/drivers/thermal/tsens2xxx.c
@@ -499,7 +499,7 @@
 			/* Use id for multiple controllers */
 			pr_debug("sensor:%d trigger temp (%d degC)\n",
 				tm->sensor[i].hw_id, temp);
-			of_thermal_handle_trip(tm->sensor[i].tzd);
+			of_thermal_handle_trip_temp(tm->sensor[i].tzd, temp);
 		}
 	}
 
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 6352d54..abb97b5 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -985,7 +985,8 @@
 		geni_write_reg_nolog(M_CMD_ABORT_EN, uport->membase,
 							SE_GENI_M_IRQ_CLEAR);
 	}
-	geni_write_reg_nolog(M_CMD_CANCEL_EN, uport, SE_GENI_M_IRQ_CLEAR);
+	geni_write_reg_nolog(M_CMD_CANCEL_EN, uport->membase,
+						SE_GENI_M_IRQ_CLEAR);
 	/*
 	 * If we end up having to cancel an on-going Tx for non-console usecase
 	 * then it means there was some unsent data in the Tx FIFO, consequently
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index d9baac6..a866332 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -424,6 +424,7 @@
 	dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
 	dwc->ep0_usb_req.request.buf = dwc->setup_buf;
 	dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
+	dwc->ep0_usb_req.request.dma = DMA_ERROR_CODE;
 
 	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
 }
@@ -760,6 +761,7 @@
 	dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
 	dwc->ep0_usb_req.request.buf = dwc->setup_buf;
 	dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
+	dwc->ep0_usb_req.request.dma = DMA_ERROR_CODE;
 
 	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
 }
diff --git a/drivers/usb/gadget/function/f_ipc.c b/drivers/usb/gadget/function/f_ipc.c
index 77440f7..3f914ce 100644
--- a/drivers/usb/gadget/function/f_ipc.c
+++ b/drivers/usb/gadget/function/f_ipc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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
@@ -265,6 +265,8 @@
 		return -EINVAL;
 	}
 
+	reinit_completion(&ipc_dev->write_done);
+
 	if (usb_ep_queue(in, req, GFP_KERNEL)) {
 		wait_event_interruptible(ipc_dev->state_wq, ipc_dev->online ||
 				ipc_dev->current_state == IPC_DISCONNECTED);
@@ -332,6 +334,8 @@
 		return -EINVAL;
 	}
 
+	reinit_completion(&ipc_dev->read_done);
+
 	if (usb_ep_queue(out, req, GFP_KERNEL)) {
 		wait_event_interruptible(ipc_dev->state_wq, ipc_dev->online ||
 				ipc_dev->current_state == IPC_DISCONNECTED);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index f9a3407..1e672a5 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -1304,8 +1304,6 @@
 
 		if (PD_RDO_OBJ_POS(pd->rdo) != 1 ||
 			PD_RDO_FIXED_CURR(pd->rdo) >
-				PD_SRC_PDO_FIXED_MAX_CURR(*default_src_caps) ||
-			PD_RDO_FIXED_CURR_MINMAX(pd->rdo) >
 				PD_SRC_PDO_FIXED_MAX_CURR(*default_src_caps)) {
 			/* send Reject */
 			ret = pd_send_msg(pd, MSG_REJECT, NULL, 0, SOP_MSG);
diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c
index 903a083..b6db0ee 100644
--- a/drivers/video/fbdev/msm/mdp3.c
+++ b/drivers/video/fbdev/msm/mdp3.c
@@ -1354,6 +1354,8 @@
 			pr_err("invalid ion client\n");
 			return -ENOMEM;
 		}
+		MDSS_XLOG(data->srcp_dma_buf, data->addr, data->len, client,
+				data->mapped, data->skip_detach);
 		if (data->mapped) {
 			if (client == MDP3_CLIENT_PPP ||
 						client == MDP3_CLIENT_DMA_P)
@@ -1520,6 +1522,13 @@
 		mdp3_put_img(data, client);
 		return -EINVAL;
 	}
+	if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+		MDSS_XLOG(img->memory_id, data->addr, data->len, fb_num);
+	} else if (iclient) {
+		MDSS_XLOG(img->memory_id, data->srcp_dma_buf, data->addr,
+				data->len, client, data->mapped,
+				data->skip_detach);
+	}
 	return ret;
 
 clone_err:
@@ -1987,6 +1996,7 @@
 
 	mdata->debug_inf.debug_enable_clock = mdp3_debug_enable_clock;
 	mdata->mdp_rev = mdp3_res->mdp_rev;
+	mdata->pdev = pdev;
 
 	rc = mdss_debugfs_init(mdata);
 	if (rc)
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 8a40d70..2238e2d 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -263,7 +263,7 @@
 	schedule_work(&mdp3_session->retire_work);
 }
 
-static void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
+void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
 {
 	struct mdp3_session_data *mdp3_session;
 
@@ -273,6 +273,10 @@
 	if (mdp3_session->retire_cnt > 0) {
 		mdss_inc_timeline(mfd->mdp_sync_pt_data.timeline_retire, val);
 		mdp3_session->retire_cnt -= min(val, mdp3_session->retire_cnt);
+		pr_debug("Retire signaled! timeline val=%d remaining=%d\n",
+			mdss_get_timeline_retire_ts(
+			mfd->mdp_sync_pt_data.timeline_retire),
+			mdp3_session->retire_cnt);
 	}
 	mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
 }
@@ -3044,7 +3048,7 @@
 	mdp3_interface->lut_update = NULL;
 	mdp3_interface->configure_panel = mdp3_update_panel_info;
 	mdp3_interface->input_event_handler = NULL;
-	mdp3_interface->signal_retire_fence = NULL;
+	mdp3_interface->signal_retire_fence = mdp3_vsync_retire_signal;
 	mdp3_interface->is_twm_en = mdp3_is_twm_en;
 
 	mdp3_session = kzalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.h b/drivers/video/fbdev/msm/mdp3_ctrl.h
index de90127..cfab411 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.h
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.h
@@ -36,6 +36,9 @@
 	int pop_idx;
 };
 
+/* struct mdp3_session_data is MDP3 fb private data */
+#define mfd_to_mdp3_data(mfd)	(mfd->mdp.private1)
+
 struct mdp3_session_data {
 	struct mutex lock;
 	int status;
@@ -92,5 +95,6 @@
 int mdp3_ctrl_reset(struct msm_fb_data_type *mfd);
 int mdp3_get_ion_client(struct msm_fb_data_type *mfd);
 void mdp3_flush_dma_done(struct mdp3_session_data *mdp3_session);
+void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val);
 
 #endif /* MDP3_CTRL_H */
diff --git a/drivers/video/fbdev/msm/mdp3_dma.c b/drivers/video/fbdev/msm/mdp3_dma.c
index e569a0b..77b22bfe 100644
--- a/drivers/video/fbdev/msm/mdp3_dma.c
+++ b/drivers/video/fbdev/msm/mdp3_dma.c
@@ -704,7 +704,11 @@
 				}
 				rc = -1;
 			}
-				ATRACE_END("mdp3_wait_for_dma_comp");
+			ATRACE_END("mdp3_wait_for_dma_comp");
+			if (rc <= 0 && retry_count == 0) {
+				MDSS_XLOG_TOUT_HANDLER("mdp", "vbif",
+						"dsi0_ctrl", "dsi0_phy");
+			}
 		}
 	}
 	if (dma->update_src_cfg) {
@@ -1084,12 +1088,17 @@
 
 	/*
 	 * Interrupts are disabled.
-	 * Check for blocked dma done interrupt.
-	 * Flush items waiting for dma done interrupt.
+	 * Check for blocked dma done and vsync interrupt.
+	 * Flush items waiting for interrupts.
 	 */
-	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD &&
-		atomic_read(&dma->session->dma_done_cnt))
-		mdp3_flush_dma_done(dma->session);
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		if (atomic_read(&dma->session->dma_done_cnt))
+			mdp3_flush_dma_done(dma->session);
+		if (dma->session->retire_cnt) {
+			mdp3_vsync_retire_signal(dma->session->mfd,
+			dma->session->retire_cnt);
+		}
+	}
 
 	return ret;
 }
diff --git a/drivers/video/fbdev/msm/mdp3_ppp.c b/drivers/video/fbdev/msm/mdp3_ppp.c
index 5459510..4886320 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp.c
@@ -318,10 +318,12 @@
 	 */
 	ret = wait_for_completion_timeout(
 	  &ppp_stat->ppp_comp, msecs_to_jiffies(200));
-	if (!ret)
+	if (!ret) {
 		pr_err("%s: Timed out waiting for the MDP.\n",
 			__func__);
-
+		MDSS_XLOG_TOUT_HANDLER("mdp", "vbif",
+				"dsi0_ctrl", "dsi0_phy");
+	}
 	return ret;
 }
 
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index da80971..3e9b7eb 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1859,6 +1859,20 @@
 	}
 }
 
+static void mdss_fb_signal_retire_fence(struct msm_fb_data_type *mfd)
+{
+#ifdef TARGET_HW_MDSS_MDP3
+	struct mdp3_session_data *mdp3_session = mfd_to_mdp3_data(mfd);
+	int retire_cnt = mdp3_session->retire_cnt;
+#else
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+	int retire_cnt = mdp5_data->retire_cnt;
+#endif
+
+	if (mfd->mdp.signal_retire_fence)
+		mfd->mdp.signal_retire_fence(mfd, retire_cnt);
+}
+
 static int mdss_fb_blank_blank(struct msm_fb_data_type *mfd,
 	int req_power_state)
 {
@@ -1906,10 +1920,13 @@
 	mfd->panel_power_state = req_power_state;
 
 	ret = mfd->mdp.off_fnc(mfd);
-	if (ret)
+	if (ret) {
 		mfd->panel_power_state = cur_power_state;
-	else if (!mdss_panel_is_power_on_interactive(req_power_state))
+	} else if (!mdss_panel_is_power_on_interactive(req_power_state)) {
 		mdss_fb_release_fences(mfd);
+		if (mfd->panel.type == MIPI_CMD_PANEL)
+			mdss_fb_signal_retire_fence(mfd);
+	}
 	mfd->op_enable = true;
 	complete(&mfd->power_off_comp);
 
@@ -3712,9 +3729,8 @@
 		 */
 		mdss_fb_release_kickoff(mfd);
 		mdss_fb_signal_timeline(sync_pt_data);
-		if ((mfd->panel.type == MIPI_CMD_PANEL) &&
-			(mfd->mdp.signal_retire_fence))
-			mfd->mdp.signal_retire_fence(mfd, 1);
+		if (mfd->panel.type == MIPI_CMD_PANEL)
+			mdss_fb_signal_retire_fence(mfd);
 		return ret;
 	}
 	if (!sync_pt_data->async_wait_fences)
@@ -3772,9 +3788,8 @@
 	if (IS_ERR_VALUE((unsigned long)ret) || !sync_pt_data->flushed) {
 		mdss_fb_release_kickoff(mfd);
 		mdss_fb_signal_timeline(sync_pt_data);
-		if ((mfd->panel.type == MIPI_CMD_PANEL) &&
-			(mfd->mdp.signal_retire_fence))
-			mfd->mdp.signal_retire_fence(mfd, 1);
+		if (mfd->panel.type == MIPI_CMD_PANEL)
+			mdss_fb_signal_retire_fence(mfd);
 	}
 
 	if (dynamic_dsi_switch) {
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index c213f70..a9a878e 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -517,7 +517,8 @@
 	} else {
 		pr_err("mdss_smmu: iova:0x%lx flags:0x%x\n",
 			iova, flags);
-		MDSS_XLOG_TOUT_HANDLER("mdp");
+		MDSS_XLOG_TOUT_HANDLER("mdp", "vbif", "dsi0_ctrl",
+				"dsi0_phy");
 	}
 end:
 	return -ENODEV;
diff --git a/include/dt-bindings/clock/msm-clocks-hwio-8952.h b/include/dt-bindings/clock/msm-clocks-hwio-8952.h
index cba5a86..a8483cb 100644
--- a/include/dt-bindings/clock/msm-clocks-hwio-8952.h
+++ b/include/dt-bindings/clock/msm-clocks-hwio-8952.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, 2018-2019, 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
@@ -294,7 +294,8 @@
 #define dsi0_1phypll_source_val         3   /* byte1_clk & pclk1_clk */
 #define dsi1_0phypll_source_val         3   /* byte0_clk & pclk0_clk */
 #define dsi1_1phypll_source_val         1   /* byte1_clk & pclk1_clk */
-
+#define gpll0_gfx_source_val		5   /* GPLL0 GFX on QM215    */
+#define gpll6_gfx_source_val		6   /* GPLL6 GFX on QM215    */
 
 #define F(f, s, div, m, n) \
 	{ \
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index 08f30a46..9d13f24 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -215,6 +215,7 @@
 int hdcp_library_register(struct hdcp_register_data *data);
 void hdcp_library_deregister(void *phdcpcontext);
 bool hdcp1_check_if_supported_load_app(void);
+void hdcp1_unload_app(void);
 int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb);
 int hdcp1_set_enc(bool enable);
 #endif /* __HDCP_QSEECOM_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index d32e7b8..29dedd4 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -497,8 +497,8 @@
  * enum perf_event_active_state - the states of a event
  */
 enum perf_event_active_state {
-	PERF_EVENT_STATE_DEAD		= -5,
-	PERF_EVENT_STATE_ZOMBIE		= -4,
+	PERF_EVENT_STATE_DORMANT	= -5,
+	PERF_EVENT_STATE_DEAD		= -4,
 	PERF_EVENT_STATE_EXIT		= -3,
 	PERF_EVENT_STATE_ERROR		= -2,
 	PERF_EVENT_STATE_OFF		= -1,
@@ -721,7 +721,13 @@
 
 	/* Is this event shared with other events */
 	bool					shared;
-	struct list_head		zombie_entry;
+
+	/*
+	 * Entry into the list that holds the events whose CPUs
+	 * are offline. These events will be installed once the
+	 * CPU wakes up and will be removed from the list after that
+	 */
+	struct list_head		dormant_event_entry;
 #endif /* CONFIG_PERF_EVENTS */
 };
 
@@ -1401,9 +1407,11 @@
 #ifdef CONFIG_PERF_EVENTS
 int perf_event_init_cpu(unsigned int cpu);
 int perf_event_exit_cpu(unsigned int cpu);
+int perf_event_restart_events(unsigned int cpu);
 #else
 #define perf_event_init_cpu	NULL
 #define perf_event_exit_cpu	NULL
+#define perf_event_restart_events NULL
 #endif
 
 #endif /* _LINUX_PERF_EVENT_H */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index a8d1fa5..1cce84e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -304,6 +304,7 @@
 	POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
 	POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
 	POWER_SUPPLY_PROP_CC_SOC,
+	POWER_SUPPLY_PROP_QG_VBMS_MODE,
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
 	/* Properties of type `const char *' */
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index dd1d142..38a66fd 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -41,6 +41,10 @@
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map	dep_map;
 #endif
+#ifdef CONFIG_RWSEM_PRIO_AWARE
+	/* count for waiters preempt to queue in wait list */
+	long m_count;
+#endif
 };
 
 extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
@@ -75,12 +79,19 @@
 #define __RWSEM_OPT_INIT(lockname)
 #endif
 
+#ifdef CONFIG_RWSEM_PRIO_AWARE
+#define __RWSEM_PRIO_AWARE_INIT(lockname)	.m_count = 0
+#else
+#define __RWSEM_PRIO_AWARE_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name)				\
 	{ __RWSEM_INIT_COUNT(name),				\
 	  .wait_list = LIST_HEAD_INIT((name).wait_list),	\
 	  .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock)	\
 	  __RWSEM_OPT_INIT(name)				\
-	  __RWSEM_DEP_MAP_INIT(name) }
+	  __RWSEM_DEP_MAP_INIT(name),				\
+	  __RWSEM_PRIO_AWARE_INIT(name) }
 
 #define DECLARE_RWSEM(name) \
 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index 99948cb..b059fd2 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -34,6 +34,8 @@
 extern unsigned int sysctl_sched_group_upmigrate_pct;
 extern unsigned int sysctl_sched_group_downmigrate_pct;
 extern unsigned int sysctl_sched_walt_rotate_big_tasks;
+extern unsigned int sysctl_sched_min_task_util_for_boost_colocation;
+extern unsigned int sysctl_sched_little_cluster_coloc_fmin_khz;
 
 extern int
 walt_proc_update_handler(struct ctl_table *table, int write,
@@ -135,4 +137,9 @@
 				 void __user *buffer, size_t *lenp,
 				 loff_t *ppos);
 
+#ifdef CONFIG_SCHED_WALT
+extern int sched_little_cluster_coloc_fmin_khz_handler(struct ctl_table *table,
+					int write, void __user *buffer,
+					size_t *lenp, loff_t *ppos);
+#endif
 #endif /* _SCHED_SYSCTL_H */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 33c1dae..b774848 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -531,6 +531,8 @@
 				       struct thermal_cooling_device *);
 void thermal_zone_device_update(struct thermal_zone_device *,
 				enum thermal_notify_event);
+void thermal_zone_device_update_temp(struct thermal_zone_device *tz,
+				enum thermal_notify_event event, int temp);
 void thermal_zone_set_trips(struct thermal_zone_device *);
 
 struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
@@ -584,6 +586,10 @@
 static inline void thermal_zone_device_update(struct thermal_zone_device *tz,
 					      enum thermal_notify_event event)
 { }
+static inline void thermal_zone_device_update_temp(
+		struct thermal_zone_device *tz, enum thermal_notify_event event,
+		int temp)
+{ }
 static inline void thermal_zone_set_trips(struct thermal_zone_device *tz)
 { }
 static inline struct thermal_cooling_device *
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 6fa28ab..fa88064 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2019, 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
@@ -42,7 +42,7 @@
 	int	is_pronto_vadc;
 	int	is_pronto_v3;
 	void __iomem	*msm_wcnss_base;
-	int	iris_id;
+	unsigned int iris_id;
 	int	vbatt;
 	struct vregs_level pronto_vlevel[PRONTO_REGULATORS];
 	struct vregs_level iris_vlevel[IRIS_REGULATORS];
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 7ef3db4..0732a6f 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -144,4 +144,5 @@
 extern bool icnss_is_fw_down(void);
 extern bool icnss_is_rejuvenate(void);
 extern int icnss_trigger_recovery(struct device *dev);
+extern void icnss_block_shutdown(bool status);
 #endif /* _ICNSS_WLAN_H_ */
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index b3ec962..be3d8b2 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -596,8 +596,14 @@
 
 TRACE_EVENT(sched_load_to_gov,
 
-	TP_PROTO(struct rq *rq, u64 aggr_grp_load, u32 tt_load, u64 freq_aggr_thresh, u64 load, int policy, int big_task_rotation),
-	TP_ARGS(rq, aggr_grp_load, tt_load, freq_aggr_thresh, load, policy, big_task_rotation),
+	TP_PROTO(struct rq *rq, u64 aggr_grp_load, u32 tt_load,
+		u64 freq_aggr_thresh, u64 load, int policy,
+		int big_task_rotation,
+		unsigned int sysctl_sched_little_cluster_coloc_fmin_khz,
+		u64 coloc_boost_load),
+	TP_ARGS(rq, aggr_grp_load, tt_load, freq_aggr_thresh, load, policy,
+		big_task_rotation, sysctl_sched_little_cluster_coloc_fmin_khz,
+		coloc_boost_load),
 
 	TP_STRUCT__entry(
 		__field(	int,	cpu			)
@@ -613,6 +619,9 @@
 		__field(	u64,	pl			)
 		__field(	u64,    load			)
 		__field(	int,    big_task_rotation	)
+		__field(unsigned int,
+				sysctl_sched_little_cluster_coloc_fmin_khz)
+		__field(	u64,	coloc_boost_load	)
 	),
 
 	TP_fast_assign(
@@ -629,14 +638,19 @@
 		__entry->pl		= rq->walt_stats.pred_demands_sum;
 		__entry->load		= load;
 		__entry->big_task_rotation = big_task_rotation;
+		__entry->sysctl_sched_little_cluster_coloc_fmin_khz =
+				sysctl_sched_little_cluster_coloc_fmin_khz;
+		__entry->coloc_boost_load = coloc_boost_load;
 	),
 
-	TP_printk("cpu=%d policy=%d ed_task_pid=%d aggr_grp_load=%llu freq_aggr_thresh=%llu tt_load=%llu rq_ps=%llu grp_rq_ps=%llu nt_ps=%llu grp_nt_ps=%llu pl=%llu load=%llu big_task_rotation=%d",
+	TP_printk("cpu=%d policy=%d ed_task_pid=%d aggr_grp_load=%llu freq_aggr_thresh=%llu tt_load=%llu rq_ps=%llu grp_rq_ps=%llu nt_ps=%llu grp_nt_ps=%llu pl=%llu load=%llu big_task_rotation=%d sysctl_sched_little_cluster_coloc_fmin_khz=%u coloc_boost_load=%llu",
 		__entry->cpu, __entry->policy, __entry->ed_task_pid,
 		__entry->aggr_grp_load, __entry->freq_aggr_thresh,
 		__entry->tt_load, __entry->rq_ps, __entry->grp_rq_ps,
 		__entry->nt_ps, __entry->grp_nt_ps, __entry->pl, __entry->load,
-		__entry->big_task_rotation)
+		__entry->big_task_rotation,
+		__entry->sysctl_sched_little_cluster_coloc_fmin_khz,
+		__entry->coloc_boost_load)
 );
 #endif
 
diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h
index 54aa362..8bd220f 100644
--- a/include/uapi/linux/qg.h
+++ b/include/uapi/linux/qg.h
@@ -21,7 +21,7 @@
 	QG_FULL_SOC,
 	QG_CLEAR_LEARNT_DATA,
 	QG_SYS_SOC,
-	QG_RESERVED_10,
+	QG_VBMS_IBAT,
 	QG_MAX,
 };
 
@@ -34,6 +34,7 @@
 #define QG_FULL_SOC QG_FULL_SOC
 #define QG_CLEAR_LEARNT_DATA QG_CLEAR_LEARNT_DATA
 #define QG_SYS_SOC QG_SYS_SOC
+#define QG_VBMS_IBAT QG_VBMS_IBAT
 
 struct fifo_data {
 	unsigned int			v;
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index ae65649..d999e4f 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -24,6 +24,7 @@
 #define CAM_FLASH_DEVICE_TYPE     (CAM_DEVICE_TYPE_BASE + 11)
 #define CAM_EEPROM_DEVICE_TYPE    (CAM_DEVICE_TYPE_BASE + 12)
 #define CAM_OIS_DEVICE_TYPE       (CAM_DEVICE_TYPE_BASE + 13)
+#define CAM_IRLED_DEVICE_TYPE     (CAM_DEVICE_TYPE_BASE + 14)
 
 /* cam_req_mgr hdl info */
 #define CAM_REQ_MGR_HDL_IDX_POS           8
diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h
index f5af604..e5c7605 100644
--- a/include/uapi/media/cam_sensor.h
+++ b/include/uapi/media/cam_sensor.h
@@ -9,6 +9,7 @@
 #define CAM_FLASH_MAX_LED_TRIGGERS 3
 #define MAX_OIS_NAME_SIZE 32
 #define CAM_CSIPHY_SECURE_MODE_ENABLED 1
+#define CAM_IR_LED_SUPPORTED
 /**
  * struct cam_sensor_query_cap - capabilities info for sensor
  *
@@ -22,6 +23,7 @@
  * @ois_slot_id      :  OIS slot id which connected to sensor
  * @flash_slot_id    :  Flash slot id which connected to sensor
  * @csiphy_slot_id   :  CSIphy slot id which connected to sensor
+ * @irled_slot_id    :  IRLED slot id which connected to sensor
  *
  */
 struct  cam_sensor_query_cap {
@@ -35,6 +37,7 @@
 	uint32_t        ois_slot_id;
 	uint32_t        flash_slot_id;
 	uint32_t        csiphy_slot_id;
+	uint32_t        ir_led_slot_id;
 } __attribute__((packed));
 
 /**
@@ -474,4 +477,29 @@
 	uint32_t    max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS];
 } __attribute__ ((packed));
 
+/**
+ * struct cam_ir_led_query_cap  :  capabilities info for ir_led
+ *
+ * @slot_info           :  Indicates about the slotId or cell Index
+ *
+ */
+struct cam_ir_led_query_cap_info {
+	uint32_t    slot_info;
+} __attribute__ ((packed));
+
+/**
+ * struct cam_ir_ledset_on_off : led turn on/off command buffer
+ *
+ * @opcode             :   command buffer opcodes
+ * @cmd_type           :   command buffer operation type
+ * @ir_led_intensity   :   ir led intensity level
+ *
+ */
+struct cam_ir_led_set_on_off {
+	uint16_t    reserved;
+	uint8_t     opcode;
+	uint8_t     cmd_type;
+	uint32_t    ir_led_intensity;
+} __attribute__((packed));
+
 #endif
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks
index ebdb004..2a31a58 100644
--- a/kernel/Kconfig.locks
+++ b/kernel/Kconfig.locks
@@ -248,3 +248,7 @@
 config QUEUED_RWLOCKS
 	def_bool y if ARCH_USE_QUEUED_RWLOCKS
 	depends on SMP
+
+config RWSEM_PRIO_AWARE
+       def_bool y
+       depends on RWSEM_XCHGADD_ALGORITHM
diff --git a/kernel/cpu.c b/kernel/cpu.c
index cc2e478..dd067c0 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1556,7 +1556,7 @@
 	},
 	[CPUHP_AP_PERF_ONLINE] = {
 		.name			= "perf:online",
-		.startup.single		= perf_event_init_cpu,
+		.startup.single		= perf_event_restart_events,
 		.teardown.single	= perf_event_exit_cpu,
 	},
 	[CPUHP_AP_WORKQUEUE_ONLINE] = {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 245d4b4..b7f83d6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2315,6 +2315,23 @@
 	perf_pmu_enable(cpuctx->ctx.pmu);
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static LIST_HEAD(dormant_event_list);
+static DEFINE_SPINLOCK(dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+	spin_lock(&dormant_event_list_lock);
+	if (event->state == PERF_EVENT_STATE_DORMANT)
+		goto out;
+
+	event->state = PERF_EVENT_STATE_DORMANT;
+	list_add_tail(&event->dormant_event_entry, &dormant_event_list);
+out:
+	spin_unlock(&dormant_event_list_lock);
+}
+#endif
+
 /*
  * Cross CPU call to install and enable a performance event
  *
@@ -2460,6 +2477,34 @@
 	raw_spin_unlock_irq(&ctx->lock);
 }
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+	struct perf_event *event, *tmp;
+	struct perf_event_context *ctx;
+
+	spin_lock(&dormant_event_list_lock);
+	list_for_each_entry_safe(event, tmp, &dormant_event_list,
+						dormant_event_entry) {
+		if (cpu != event->cpu)
+			continue;
+
+		list_del(&event->dormant_event_entry);
+		event->state = PERF_EVENT_STATE_INACTIVE;
+		spin_unlock(&dormant_event_list_lock);
+
+		ctx = event->ctx;
+
+		mutex_lock(&ctx->mutex);
+		perf_install_in_context(ctx, event, cpu);
+		mutex_unlock(&ctx->mutex);
+
+		spin_lock(&dormant_event_list_lock);
+	}
+	spin_unlock(&dormant_event_list_lock);
+}
+#endif
+
 /*
  * Put a event into inactive state and update time fields.
  * Enabling the leader of a group effectively enables all
@@ -4277,14 +4322,6 @@
 }
 
 /*
- * Maintain a zombie list to collect all the zombie events
- */
-#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-static LIST_HEAD(zombie_list);
-static DEFINE_SPINLOCK(zombie_list_lock);
-#endif
-
-/*
  * Kill an event dead; while event:refcount will preserve the event
  * object, it will not preserve its functionality. Once the last 'user'
  * gives up the object, we'll destroy the thing.
@@ -4294,23 +4331,12 @@
 	struct perf_event_context *ctx = event->ctx;
 	struct perf_event *child, *tmp;
 
-	/*
-	 * If the cpu associated to this event is offline, set the event as a
-	 *  zombie event. The cleanup of the cpu would be done if the CPU is
-	 *  back online.
-	 */
 #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-	if (event->cpu != -1 && per_cpu(is_hotplugging, event->cpu)) {
-		if (event->state == PERF_EVENT_STATE_ZOMBIE)
-			return 0;
-
-		event->state = PERF_EVENT_STATE_ZOMBIE;
-
-		spin_lock(&zombie_list_lock);
-		list_add_tail(&event->zombie_entry, &zombie_list);
-		spin_unlock(&zombie_list_lock);
-
-		return 0;
+	if (event->cpu != -1) {
+		spin_lock(&dormant_event_list_lock);
+		if (event->state == PERF_EVENT_STATE_DORMANT)
+			list_del(&event->dormant_event_entry);
+		spin_unlock(&dormant_event_list_lock);
 	}
 #endif
 
@@ -4632,6 +4658,15 @@
 	struct perf_event_context *ctx;
 	int ret;
 
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+	spin_lock(&dormant_event_list_lock);
+	if (event->state == PERF_EVENT_STATE_DORMANT) {
+		spin_unlock(&dormant_event_list_lock);
+		return 0;
+	}
+	spin_unlock(&dormant_event_list_lock);
+#endif
+
 	ctx = perf_event_ctx_lock(event);
 	ret = __perf_read(event, buf, count);
 	perf_event_ctx_unlock(event, ctx);
@@ -9466,13 +9501,13 @@
 	mutex_init(&event->child_mutex);
 	INIT_LIST_HEAD(&event->child_list);
 
+	INIT_LIST_HEAD(&event->dormant_event_entry);
 	INIT_LIST_HEAD(&event->group_entry);
 	INIT_LIST_HEAD(&event->event_entry);
 	INIT_LIST_HEAD(&event->sibling_list);
 	INIT_LIST_HEAD(&event->rb_entry);
 	INIT_LIST_HEAD(&event->active_entry);
 	INIT_LIST_HEAD(&event->addr_filters.list);
-	INIT_LIST_HEAD(&event->zombie_entry);
 	INIT_HLIST_NODE(&event->hlist_entry);
 
 
@@ -11125,111 +11160,27 @@
 }
 
 #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-static void
-check_hotplug_start_event(struct perf_event *event)
+int perf_event_restart_events(unsigned int cpu)
 {
-	if (event->pmu->events_across_hotplug &&
-	    event->attr.type == PERF_TYPE_SOFTWARE &&
-	    event->pmu->start)
-		event->pmu->start(event, 0);
-}
-
-static void perf_event_zombie_cleanup(unsigned int cpu)
-{
-	struct perf_event *event, *tmp;
-
-	spin_lock(&zombie_list_lock);
-
-	list_for_each_entry_safe(event, tmp, &zombie_list, zombie_entry) {
-		if (event->cpu != cpu)
-			continue;
-
-		list_del(&event->zombie_entry);
-		spin_unlock(&zombie_list_lock);
-
-		/*
-		 * The detachment of the event with the
-		 * PMU expects it to be in an active state
-		 */
-		event->state = PERF_EVENT_STATE_ACTIVE;
-		__perf_event_release_kernel(event);
-
-		spin_lock(&zombie_list_lock);
-	}
-
-	spin_unlock(&zombie_list_lock);
-}
-
-static int perf_event_start_swevents(unsigned int cpu)
-{
-	struct perf_event_context *ctx;
-	struct pmu *pmu;
-	struct perf_event *event;
-	int idx;
-
 	mutex_lock(&pmus_lock);
-	perf_event_zombie_cleanup(cpu);
-
-	idx = srcu_read_lock(&pmus_srcu);
-	list_for_each_entry_rcu(pmu, &pmus, entry) {
-		ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
-		mutex_lock(&ctx->mutex);
-		raw_spin_lock(&ctx->lock);
-		list_for_each_entry(event, &ctx->event_list, event_entry)
-			check_hotplug_start_event(event);
-		raw_spin_unlock(&ctx->lock);
-		mutex_unlock(&ctx->mutex);
-	}
-	srcu_read_unlock(&pmus_srcu, idx);
 	per_cpu(is_hotplugging, cpu) = false;
+	perf_deferred_install_in_context(cpu);
 	mutex_unlock(&pmus_lock);
 
 	return 0;
 }
 
-/*
- * If keeping events across hotplugging is supported, do not
- * remove the event list so event lives beyond CPU hotplug.
- * The context is exited via an fd close path when userspace
- * is done and the target CPU is online. If software clock
- * event is active, then stop hrtimer associated with it.
- * Start the timer when the CPU comes back online.
- */
-static void
-check_hotplug_remove_from_context(struct perf_event *event,
-			   struct perf_cpu_context *cpuctx,
-			   struct perf_event_context *ctx)
-{
-	if (event->pmu->events_across_hotplug &&
-	    event->attr.type == PERF_TYPE_SOFTWARE &&
-	    event->pmu->stop)
-		event->pmu->stop(event, PERF_EF_UPDATE);
-	else if (!event->pmu->events_across_hotplug)
-		__perf_remove_from_context(event, cpuctx,
-			ctx, (void *)DETACH_GROUP);
-}
-
-static void __perf_event_exit_context(void *__info)
-{
-	struct perf_event_context *ctx = __info;
-	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-	struct perf_event *event;
-
-	raw_spin_lock(&ctx->lock);
-	list_for_each_entry(event, &ctx->event_list, event_entry)
-		check_hotplug_remove_from_context(event, cpuctx, ctx);
-	raw_spin_unlock(&ctx->lock);
-}
-
 static void perf_event_exit_cpu_context(int cpu)
 {
 	struct perf_cpu_context *cpuctx;
 	struct perf_event_context *ctx;
 	unsigned long flags;
+	struct perf_event *event, *event_tmp;
 	struct pmu *pmu;
 	int idx;
 
 	idx = srcu_read_lock(&pmus_srcu);
+	per_cpu(is_hotplugging, cpu) = true;
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
 		ctx = &cpuctx->ctx;
@@ -11244,7 +11195,12 @@
 		}
 
 		mutex_lock(&ctx->mutex);
-		smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
+		list_for_each_entry_safe(event, event_tmp, &ctx->event_list,
+								event_entry) {
+			perf_remove_from_context(event, DETACH_GROUP);
+			if (event->pmu->events_across_hotplug)
+				perf_prepare_install_in_context(event);
+		}
 		mutex_unlock(&ctx->mutex);
 	}
 	srcu_read_unlock(&pmus_srcu, idx);
@@ -11257,8 +11213,8 @@
 
 int perf_event_exit_cpu(unsigned int cpu)
 {
+
 	mutex_lock(&pmus_lock);
-	per_cpu(is_hotplugging, cpu) = true;
 	perf_event_exit_cpu_context(cpu);
 	mutex_unlock(&pmus_lock);
 	return 0;
@@ -11303,25 +11259,6 @@
 	.notifier_call = event_idle_notif,
 };
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int perf_cpu_hp_init(void)
-{
-	int ret;
-
-	ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ONLINE,
-				"PERF/CORE/CPUHP_AP_PERF_ONLINE",
-				perf_event_start_swevents,
-				perf_event_exit_cpu);
-	if (ret)
-		pr_err("CPU hotplug notifier for perf core could not be registered: %d\n",
-		       ret);
-
-	return ret;
-}
-#else
-static int perf_cpu_hp_init(void) { return 0; }
-#endif
-
 void __init perf_event_init(void)
 {
 	int ret, cpu;
@@ -11348,8 +11285,6 @@
 	perf_event_init_cpu(smp_processor_id());
 	idle_notifier_register(&perf_event_idle_nb);
 	register_reboot_notifier(&perf_reboot_notifier);
-	ret = perf_cpu_hp_init();
-	WARN(ret, "core perf_cpu_hp_init() failed with: %d", ret);
 
 	ret = init_hw_breakpoint();
 	WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index a4112df..15be517 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -87,21 +87,13 @@
 	sem->owner = NULL;
 	osq_lock_init(&sem->osq);
 #endif
+#ifdef CONFIG_RWSEM_PRIO_AWARE
+	sem->m_count = 0;
+#endif
 }
 
 EXPORT_SYMBOL(__init_rwsem);
 
-enum rwsem_waiter_type {
-	RWSEM_WAITING_FOR_WRITE,
-	RWSEM_WAITING_FOR_READ
-};
-
-struct rwsem_waiter {
-	struct list_head list;
-	struct task_struct *task;
-	enum rwsem_waiter_type type;
-};
-
 enum rwsem_wake_type {
 	RWSEM_WAKE_ANY,		/* Wake whatever's at head of wait list */
 	RWSEM_WAKE_READERS,	/* Wake readers only */
@@ -226,6 +218,7 @@
 	struct rwsem_waiter waiter;
 	struct task_struct *tsk = current;
 	WAKE_Q(wake_q);
+	bool is_first_waiter = false;
 
 	waiter.task = tsk;
 	waiter.type = RWSEM_WAITING_FOR_READ;
@@ -233,7 +226,9 @@
 	raw_spin_lock_irq(&sem->wait_lock);
 	if (list_empty(&sem->wait_list))
 		adjustment += RWSEM_WAITING_BIAS;
-	list_add_tail(&waiter.list, &sem->wait_list);
+
+	/* is_first_waiter == true means we are first in the queue */
+	is_first_waiter = rwsem_list_add_per_prio(&waiter, sem);
 
 	/* we're now waiting on the lock, but no longer actively locking */
 	count = atomic_long_add_return(adjustment, &sem->count);
@@ -246,7 +241,8 @@
 	 */
 	if (count == RWSEM_WAITING_BIAS ||
 	    (count > RWSEM_WAITING_BIAS &&
-	     adjustment != -RWSEM_ACTIVE_READ_BIAS))
+	     (adjustment != -RWSEM_ACTIVE_READ_BIAS ||
+	     is_first_waiter)))
 		__rwsem_mark_wake(sem, RWSEM_WAKE_ANY, &wake_q);
 
 	raw_spin_unlock_irq(&sem->wait_lock);
@@ -462,6 +458,7 @@
 	struct rwsem_waiter waiter;
 	struct rw_semaphore *ret = sem;
 	WAKE_Q(wake_q);
+	bool is_first_waiter = false;
 
 	/* undo write bias from down_write operation, stop active locking */
 	count = atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS, &sem->count);
@@ -483,7 +480,11 @@
 	if (list_empty(&sem->wait_list))
 		waiting = false;
 
-	list_add_tail(&waiter.list, &sem->wait_list);
+	/*
+	 * is_first_waiter == true means we are first in the queue,
+	 * so there is no read locks that were queued ahead of us.
+	 */
+	is_first_waiter = rwsem_list_add_per_prio(&waiter, sem);
 
 	/* we're now waiting on the lock, but no longer actively locking */
 	if (waiting) {
@@ -494,7 +495,7 @@
 		 * no active writers, the lock must be read owned; so we try to
 		 * wake any read locks that were queued ahead of us.
 		 */
-		if (count > RWSEM_WAITING_BIAS) {
+		if (!is_first_waiter && count > RWSEM_WAITING_BIAS) {
 			WAKE_Q(wake_q);
 
 			__rwsem_mark_wake(sem, RWSEM_WAKE_READERS, &wake_q);
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h
index a699f40..b60c842 100644
--- a/kernel/locking/rwsem.h
+++ b/kernel/locking/rwsem.h
@@ -15,6 +15,17 @@
  */
 #define RWSEM_READER_OWNED	((struct task_struct *)1UL)
 
+enum rwsem_waiter_type {
+	RWSEM_WAITING_FOR_WRITE,
+	RWSEM_WAITING_FOR_READ
+};
+
+struct rwsem_waiter {
+	struct list_head list;
+	struct task_struct *task;
+	enum rwsem_waiter_type type;
+};
+
 #ifdef CONFIG_RWSEM_SPIN_ON_OWNER
 /*
  * All writes to owner are protected by WRITE_ONCE() to make sure that
@@ -66,3 +77,60 @@
 {
 }
 #endif
+
+#ifdef CONFIG_RWSEM_PRIO_AWARE
+
+#define RWSEM_MAX_PREEMPT_ALLOWED 3000
+
+/*
+ * Return true if current waiter is added in the front of the rwsem wait list.
+ */
+static inline bool rwsem_list_add_per_prio(struct rwsem_waiter *waiter_in,
+				    struct rw_semaphore *sem)
+{
+	struct list_head *pos;
+	struct list_head *head;
+	struct rwsem_waiter *waiter = NULL;
+
+	pos = head = &sem->wait_list;
+	/*
+	 * Rules for task prio aware rwsem wait list queueing:
+	 * 1:	Only try to preempt waiters with which task priority
+	 *	which is higher than DEFAULT_PRIO.
+	 * 2:	To avoid starvation, add count to record
+	 *	how many high priority waiters preempt to queue in wait
+	 *	list.
+	 *	If preempt count is exceed RWSEM_MAX_PREEMPT_ALLOWED,
+	 *	use simple fifo until wait list is empty.
+	 */
+	if (list_empty(head)) {
+		list_add_tail(&waiter_in->list, head);
+		sem->m_count = 0;
+		return true;
+	}
+
+	if (waiter_in->task->prio < DEFAULT_PRIO
+		&& sem->m_count < RWSEM_MAX_PREEMPT_ALLOWED) {
+
+		list_for_each(pos, head) {
+			waiter = list_entry(pos, struct rwsem_waiter, list);
+			if (waiter->task->prio > waiter_in->task->prio) {
+				list_add(&waiter_in->list, pos->prev);
+				sem->m_count++;
+				return &waiter_in->list == head->next;
+			}
+		}
+	}
+
+	list_add_tail(&waiter_in->list, head);
+
+	return false;
+}
+#else
+static inline bool rwsem_list_add_per_prio(struct rwsem_waiter *waiter_in,
+				    struct rw_semaphore *sem)
+{
+	list_add_tail(&waiter_in->list, &sem->wait_list);
+	return false;
+}
+#endif
diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c
index 01daf82..08ada30 100644
--- a/kernel/sched/energy.c
+++ b/kernel/sched/energy.c
@@ -301,6 +301,8 @@
 		walt_sched_energy_populated_callback();
 	}
 
+	walt_map_freq_to_load();
+
 	dev_info(&pdev->dev, "Sched-energy-costs capacity updated\n");
 	return 0;
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 3b74f5f..46a9112 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -166,6 +166,10 @@
 unsigned int sysctl_sched_capacity_margin_down = 1205; /* ~15% margin */
 #define capacity_margin sysctl_sched_capacity_margin
 
+#ifdef CONFIG_SCHED_WALT
+unsigned int sysctl_sched_min_task_util_for_boost_colocation;
+#endif
+
 static inline void update_load_add(struct load_weight *lw, unsigned long inc)
 {
 	lw->weight += inc;
@@ -6172,8 +6176,7 @@
 	if (capacity == max_capacity)
 		return true;
 
-	if (sched_boost_policy() == SCHED_BOOST_ON_BIG &&
-					task_sched_boost(p))
+	if (task_boost_policy(p) == SCHED_BOOST_ON_BIG)
 		return false;
 
 	return __task_fits(p, cpu, 0);
@@ -6839,7 +6842,7 @@
 struct find_best_target_env {
 	struct cpumask *rtg_target;
 	bool need_idle;
-	bool placement_boost;
+	int placement_boost;
 	bool avoid_prev_cpu;
 };
 
@@ -7229,7 +7232,7 @@
 			if (best_idle_cpu != -1)
 				break;
 
-			if (fbt_env->placement_boost) {
+			if (fbt_env->placement_boost != SCHED_BOOST_NONE) {
 				target_capacity = ULONG_MAX;
 				continue;
 			}
@@ -7366,7 +7369,7 @@
 	return cpumask_test_cpu(cpu, tsk_cpus_allowed(p)) &&
 	       cpu_active(cpu) && !cpu_isolated(cpu) &&
 	       capacity_orig_of(cpu) >= capacity_orig_of(rtg_target_cpu) &&
-	       task_fits_max(p, cpu) && !__cpu_overutilized(cpu, task_util(p));
+	       task_fits_max(p, cpu);
 }
 
 #define SCHED_SELECT_PREV_CPU_NSEC	2000000
@@ -7411,7 +7414,9 @@
 	rcu_read_lock();
 
 	grp = task_related_thread_group(p);
-	if (grp && grp->preferred_cluster) {
+	if (grp && grp->preferred_cluster &&
+			(task_util(p) >
+			sysctl_sched_min_task_util_for_boost_colocation)) {
 		rtg_target = &grp->preferred_cluster->cpus;
 		if (!task_fits_max(p, cpumask_first(rtg_target)))
 			rtg_target = NULL;
@@ -7469,9 +7474,8 @@
 	} else {
 		fbt_env.need_idle = wake_to_idle(p);
 	}
-	fbt_env.placement_boost = task_sched_boost(p) ?
-				  sched_boost_policy() != SCHED_BOOST_NONE :
-				  false;
+
+	fbt_env.placement_boost = task_boost_policy(p);
 	fbt_env.avoid_prev_cpu = false;
 
 	if (prefer_idle || fbt_env.need_idle)
@@ -8398,7 +8402,8 @@
 	env->flags &= ~LBF_ALL_PINNED;
 
 	if (energy_aware() && !env->dst_rq->rd->overutilized &&
-	    env->idle == CPU_NEWLY_IDLE) {
+	    env->idle == CPU_NEWLY_IDLE &&
+	    !task_in_related_thread_group(p)) {
 		long util_cum_dst, util_cum_src;
 		unsigned long demand;
 
@@ -9717,7 +9722,6 @@
 
 	if (energy_aware() && !env->dst_rq->rd->overutilized) {
 		int cpu_local, cpu_busiest;
-		long util_cum;
 		unsigned long energy_local, energy_busiest;
 
 		if (env->idle != CPU_NEWLY_IDLE)
@@ -9737,10 +9741,6 @@
 		} else if (energy_local == energy_busiest) {
 			if (cpu_rq(cpu_busiest)->nr_running < 2)
 				goto out_balanced;
-
-			util_cum = cpu_util_cum(cpu_busiest, 0);
-			if (util_cum < cpu_util_cum(cpu_local, 0))
-				goto out_balanced;
 		}
 	}
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index b93d516..9942e02 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -86,6 +86,7 @@
 	int notifier_sent;
 	bool wake_up_idle;
 	u64 aggr_grp_load;
+	u64 coloc_boost_load;
 };
 
 extern unsigned int sched_disable_window_stats;
@@ -2701,6 +2702,32 @@
 extern void walt_sched_energy_populated_callback(void);
 extern void walt_update_min_max_capacity(void);
 
+static inline enum sched_boost_policy task_boost_policy(struct task_struct *p)
+{
+	enum sched_boost_policy boost_on_big = task_sched_boost(p) ?
+				sched_boost_policy() : SCHED_BOOST_NONE;
+
+	if (boost_on_big) {
+		/*
+		 * Filter out tasks less than min task util threshold
+		 * under conservative boost.
+		 */
+		if (sysctl_sched_boost == CONSERVATIVE_BOOST &&
+				task_util(p) <=
+				sysctl_sched_min_task_util_for_boost_colocation)
+			boost_on_big = SCHED_BOOST_NONE;
+	}
+
+	return boost_on_big;
+}
+
+extern void walt_map_freq_to_load(void);
+
+static inline bool is_min_capacity_cluster(struct sched_cluster *cluster)
+{
+	return is_min_capacity_cpu(cluster_first_cpu(cluster));
+}
+
 #else	/* CONFIG_SCHED_WALT */
 
 struct walt_sched_stats;
@@ -2711,7 +2738,10 @@
 {
 	return true;
 }
-
+static inline enum sched_boost_policy task_boost_policy(struct task_struct *p)
+{
+	return SCHED_BOOST_NONE;
+}
 static inline void check_for_migration(struct rq *rq, struct task_struct *p) { }
 
 static inline int sched_boost(void)
@@ -2835,6 +2865,7 @@
 static inline void walt_sched_energy_populated_callback(void) { }
 static inline void walt_update_min_max_capacity(void) { }
 
+static inline void walt_map_freq_to_load(void) { }
 #endif	/* CONFIG_SCHED_WALT */
 
 static inline bool energy_aware(void)
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 5184252..48f64aa 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -523,6 +523,7 @@
 	struct sched_cluster *cluster = rq->cluster;
 	u64 aggr_grp_load = cluster->aggr_grp_load;
 	u64 load, tt_load = 0;
+	u64 coloc_boost_load = cluster->coloc_boost_load;
 
 	if (rq->ed_task != NULL) {
 		load = sched_ravg_window;
@@ -534,6 +535,9 @@
 	else
 		load = rq->prev_runnable_sum + rq->grp_time.prev_runnable_sum;
 
+	if (coloc_boost_load)
+		load = max_t(u64, load, coloc_boost_load);
+
 	tt_load = top_task_load(rq);
 	switch (reporting_policy) {
 	case FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK:
@@ -550,7 +554,9 @@
 
 done:
 	trace_sched_load_to_gov(rq, aggr_grp_load, tt_load, freq_aggr_thresh,
-				load, reporting_policy, walt_rotation_enabled);
+				load, reporting_policy, walt_rotation_enabled,
+				sysctl_sched_little_cluster_coloc_fmin_khz,
+				coloc_boost_load);
 	return load;
 }
 
@@ -2385,6 +2391,7 @@
 	.notifier_sent		=	0,
 	.wake_up_idle		=	0,
 	.aggr_grp_load		=	0,
+	.coloc_boost_load	=	0,
 };
 
 void init_clusters(void)
@@ -2627,7 +2634,6 @@
 {
 	struct task_struct *p;
 	u64 combined_demand = 0;
-	bool boost_on_big = sched_boost_policy() == SCHED_BOOST_ON_BIG;
 	bool group_boost = false;
 	u64 wallclock;
 
@@ -2651,7 +2657,7 @@
 		return;
 
 	list_for_each_entry(p, &grp->tasks, grp_list) {
-		if (boost_on_big && task_sched_boost(p)) {
+		if (task_boost_policy(p) == SCHED_BOOST_ON_BIG) {
 			group_boost = true;
 			break;
 		}
@@ -3161,6 +3167,70 @@
 	BUG_ON((s64)*src_nt_prev_runnable_sum < 0);
 }
 
+unsigned int sysctl_sched_little_cluster_coloc_fmin_khz;
+static u64 coloc_boost_load;
+
+void walt_map_freq_to_load(void)
+{
+	struct sched_cluster *cluster;
+
+	for_each_sched_cluster(cluster) {
+		if (is_min_capacity_cluster(cluster)) {
+			int fcpu = cluster_first_cpu(cluster);
+
+			coloc_boost_load = div64_u64(
+				((u64)sched_ravg_window *
+				arch_scale_cpu_capacity(NULL, fcpu) *
+				sysctl_sched_little_cluster_coloc_fmin_khz),
+				(u64)1024 * cpu_max_possible_freq(fcpu));
+			coloc_boost_load = div64_u64(coloc_boost_load << 2, 5);
+			break;
+		}
+	}
+}
+
+static void walt_update_coloc_boost_load(void)
+{
+	struct related_thread_group *grp;
+	struct sched_cluster *cluster;
+
+	if (!sysctl_sched_little_cluster_coloc_fmin_khz ||
+			sysctl_sched_boost == CONSERVATIVE_BOOST)
+		return;
+
+	grp = lookup_related_thread_group(DEFAULT_CGROUP_COLOC_ID);
+	if (!grp || !grp->preferred_cluster ||
+			is_min_capacity_cluster(grp->preferred_cluster))
+		return;
+
+	for_each_sched_cluster(cluster) {
+		if (is_min_capacity_cluster(cluster)) {
+			cluster->coloc_boost_load = coloc_boost_load;
+			break;
+		}
+	}
+}
+
+int sched_little_cluster_coloc_fmin_khz_handler(struct ctl_table *table,
+				int write, void __user *buffer, size_t *lenp,
+				loff_t *ppos)
+{
+	int ret;
+	static DEFINE_MUTEX(mutex);
+
+	mutex_lock(&mutex);
+
+	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	if (ret || !write)
+		goto done;
+
+	walt_map_freq_to_load();
+
+done:
+	mutex_unlock(&mutex);
+	return ret;
+}
+
 /*
  * Runs in hard-irq context. This should ideally run just after the latest
  * window roll-over.
@@ -3170,7 +3240,7 @@
 	struct sched_cluster *cluster;
 	struct rq *rq;
 	int cpu;
-	u64 wc;
+	u64 wc, total_grp_load = 0;
 	int flag = SCHED_CPUFREQ_WALT;
 	bool is_migration = false;
 	int level = 0;
@@ -3206,10 +3276,15 @@
 		}
 
 		cluster->aggr_grp_load = aggr_grp_load;
+		total_grp_load = aggr_grp_load;
+		cluster->coloc_boost_load = 0;
 
 		raw_spin_unlock(&cluster->load_lock);
 	}
 
+	if (total_grp_load)
+		walt_update_coloc_boost_load();
+
 	for_each_sched_cluster(cluster) {
 		for_each_cpu(cpu, &cluster->cpus) {
 			int nflag = flag;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 90dce2a..1e49ef6 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -127,8 +127,9 @@
 static int __maybe_unused four = 4;
 static unsigned long one_ul = 1;
 static int one_hundred = 100;
-#ifdef CONFIG_PERF_EVENTS
-static int one_thousand = 1000;
+static int __maybe_unused one_thousand = 1000;
+#ifdef CONFIG_SCHED_WALT
+static int two_million = 2000000;
 #endif
 #ifdef CONFIG_PRINTK
 static int ten_thousand = 10000;
@@ -357,6 +358,24 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
+	{
+		.procname	= "sched_min_task_util_for_boost_colocation",
+		.data		= &sysctl_sched_min_task_util_for_boost_colocation,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &one_thousand,
+	},
+	{
+		.procname	= "sched_little_cluster_coloc_fmin_khz",
+		.data		= &sysctl_sched_little_cluster_coloc_fmin_khz,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= sched_little_cluster_coloc_fmin_khz_handler,
+		.extra1		= &zero,
+		.extra2		= &two_million,
+	},
 #endif
 	{
 		.procname	= "sched_upmigrate",
diff --git a/mm/memory.c b/mm/memory.c
index 0e57734..5956d6f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -934,6 +934,7 @@
 	spinlock_t *src_ptl, *dst_ptl;
 	int progress = 0;
 	int rss[NR_MM_COUNTERS];
+	unsigned long orig_addr = addr;
 	swp_entry_t entry = (swp_entry_t){0};
 
 again:
@@ -972,6 +973,15 @@
 	} while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
 
 	arch_leave_lazy_mmu_mode();
+
+	/*
+	 * Prevent the page fault handler to copy the page while stale tlb entry
+	 * are still not flushed.
+	 */
+	if (IS_ENABLED(CONFIG_SPECULATIVE_PAGE_FAULT) &&
+	    is_cow_mapping(vma->vm_flags))
+		flush_tlb_range(vma, orig_addr, end);
+
 	spin_unlock(src_ptl);
 	pte_unmap(orig_src_pte);
 	add_mm_rss_vec(dst_mm, rss);
diff --git a/mm/usercopy.c b/mm/usercopy.c
index 3c8da0a..7683c22 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -124,7 +124,7 @@
 static inline const char *check_bogus_address(const void *ptr, unsigned long n)
 {
 	/* Reject if object wraps past end of memory. */
-	if ((unsigned long)ptr + n < (unsigned long)ptr)
+	if ((unsigned long)ptr + (n - 1) < (unsigned long)ptr)
 		return "<wrapped address>";
 
 	/* Reject if NULL or ZERO-allocation. */
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index e463a3a..b0fa56c 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1,6 +1,6 @@
 /* SIP extension for IP connection tracking.
  *
- * Copyright (c) 2015,2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015,2017-2019 The Linux Foundation. All rights reserved.
  * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
  * based on RR's ip_conntrack_ftp.c and other modules.
  * (C) 2007 United Security Providers
@@ -392,8 +392,13 @@
 	return 0;
 }
 
+static void nf_hook_drop_sip(struct net *net, const struct nf_hook_entry *hook)
+{
+}
+
 static const struct nf_queue_handler nf_sip_qh = {
 	.outfn	= &nf_sip_enqueue_packet,
+	.nf_hook_drop	= &nf_hook_drop_sip,
 };
 
 static
diff --git a/net/netfilter/xt_HARDIDLETIMER.c b/net/netfilter/xt_HARDIDLETIMER.c
index c6f70da9..fdf2649 100644
--- a/net/netfilter/xt_HARDIDLETIMER.c
+++ b/net/netfilter/xt_HARDIDLETIMER.c
@@ -236,6 +236,9 @@
 	struct hardidletimer_tg_info *info = par->targinfo;
 	int ret;
 	ktime_t tout;
+	struct timespec ktimespec;
+
+	memset(&ktimespec, 0, sizeof(struct timespec));
 
 	pr_debug("checkentry targinfo %s\n", info->label);
 
@@ -256,14 +259,15 @@
 	info->timer = __hardidletimer_tg_find_by_label(info->label);
 	if (info->timer) {
 		info->timer->refcnt++;
-		if (!info->timer->active) {
-			schedule_work(&info->timer->work);
-			pr_debug("Starting Checkentry timer\n");
-		}
+		/* calculate remaining expiry time */
+		tout = alarm_expires_remaining(&info->timer->alarm);
+		ktimespec = ktime_to_timespec(tout);
 
-		info->timer->active = true;
-		tout = ktime_set(info->timeout, 0);
-		alarm_start_relative(&info->timer->alarm, tout);
+		if (ktimespec.tv_sec > 0) {
+			pr_debug("time_expiry_remaining %ld\n",
+				 ktimespec.tv_sec);
+			alarm_start_relative(&info->timer->alarm, tout);
+		}
 
 		pr_debug("increased refcnt of timer %s to %u\n",
 			 info->label, info->timer->refcnt);
diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c
index bc1829e..28adb7f 100644
--- a/net/rmnet_data/rmnet_data_config.c
+++ b/net/rmnet_data/rmnet_data_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 2019 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
@@ -800,6 +800,7 @@
 				 u16 agg_count)
 {
 	struct rmnet_phys_ep_config *config;
+	unsigned long flags;
 
 	ASSERT_RTNL();
 
@@ -815,8 +816,11 @@
 		return RMNET_CONFIG_UNKNOWN_ERROR;
 
 	config->egress_data_format = egress_data_format;
+
+	spin_lock_irqsave(&config->agg_lock, flags);
 	config->egress_agg_size = agg_size;
 	config->egress_agg_count = agg_count;
+	spin_unlock_irqrestore(&config->agg_lock, flags);
 
 	return RMNET_CONFIG_OK;
 }
diff --git a/net/rmnet_data/rmnet_map_data.c b/net/rmnet_data/rmnet_map_data.c
index 771a6b7..3ad30cf 100644
--- a/net/rmnet_data/rmnet_map_data.c
+++ b/net/rmnet_data/rmnet_map_data.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, 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
@@ -261,8 +261,10 @@
 		 * sparse, don't aggregate. We will need to tune this later
 		 */
 		diff = timespec_sub(config->agg_last, last);
+		size = config->egress_agg_size - skb->len;
 
-		if ((diff.tv_sec > 0) || (diff.tv_nsec > agg_bypass_time)) {
+		if ((diff.tv_sec > 0) || (diff.tv_nsec > agg_bypass_time) ||
+		    (size <= 0)) {
 			spin_unlock_irqrestore(&config->agg_lock, flags);
 			LOGL("delta t: %ld.%09lu\tcount: bypass", diff.tv_sec,
 			     diff.tv_nsec);
@@ -274,7 +276,6 @@
 			return;
 		}
 
-		size = config->egress_agg_size - skb->len;
 		config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC);
 		if (!config->agg_skb) {
 			config->agg_skb = 0;
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index d1fbff3..7021367 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -25,20 +25,20 @@
 
 country AF: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country AI: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country AL: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -49,8 +49,8 @@
 
 country AN: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -73,8 +73,8 @@
 
 country AT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -92,8 +92,8 @@
 
 country AW: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country AZ: DFS-ETSI
@@ -103,8 +103,8 @@
 
 country BA: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -120,8 +120,8 @@
 
 country BE: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -136,8 +136,8 @@
 
 country BG: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -150,8 +150,8 @@
 
 country BL: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country BM: DFS-FCC
@@ -192,14 +192,14 @@
 
 country BT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country BY: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country BZ:
@@ -226,8 +226,8 @@
 
 country CH: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -281,8 +281,8 @@
 
 country CY: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -292,8 +292,8 @@
 # and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
 country CZ: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -307,8 +307,8 @@
 country DE: DFS-ETSI
 	# entries 279004 and 280006
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -316,8 +316,8 @@
 
 country DK: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -352,8 +352,8 @@
 
 country EE: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -366,8 +366,8 @@
 
 country ES: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -375,14 +375,14 @@
 
 country ET: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country FI: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -397,8 +397,8 @@
 
 country FR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -406,8 +406,8 @@
 
 country GB: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -427,8 +427,8 @@
 
 country GF: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -441,26 +441,26 @@
 
 country GI: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country GL: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country GP: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country GR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -468,8 +468,8 @@
 
 country GT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country GU: DFS-FCC
@@ -504,8 +504,8 @@
 
 country HR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -520,8 +520,8 @@
 
 country HU: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -534,8 +534,8 @@
 
 country IE: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -557,14 +557,14 @@
 
 country IQ: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country IS: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -572,8 +572,8 @@
 
 country IT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -611,8 +611,8 @@
 
 country KH: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country KN: DFS-FCC
@@ -663,8 +663,8 @@
 
 country LI: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -679,14 +679,14 @@
 
 country LS: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country LT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -694,8 +694,8 @@
 
 country LU: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -703,8 +703,8 @@
 
 country LV: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -719,29 +719,29 @@
 
 country MC: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
 country MD: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
 country ME: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
 country MF: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country MH: DFS-FCC
@@ -753,8 +753,8 @@
 
 country MK: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -785,21 +785,21 @@
 
 country MQ: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
 country MR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country MT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -807,8 +807,8 @@
 
 country MU: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -820,8 +820,8 @@
 
 country MW: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country MX: DFS-FCC
@@ -865,8 +865,8 @@
 
 country NL: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -874,8 +874,8 @@
 
 country NO: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -897,8 +897,8 @@
 
 country OM: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country PA:
@@ -917,8 +917,8 @@
 
 country PF: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -944,8 +944,8 @@
 
 country PL: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -953,8 +953,8 @@
 
 country PM: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -974,8 +974,8 @@
 
 country PT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1006,14 +1006,14 @@
 
 country RE: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country RO: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1023,8 +1023,8 @@
 # http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
 country RS: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-        (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+        (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1054,8 +1054,8 @@
 
 country SE: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1072,8 +1072,8 @@
 
 country SI: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1081,8 +1081,8 @@
 
 country SK: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1096,8 +1096,8 @@
 
 country SR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country SV: DFS-FCC
@@ -1115,14 +1115,14 @@
 
 country TD: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country TG: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 40), (23)
-	(5250 - 5330 @ 40), (23), DFS
+	(5170 - 5250 @ 40), (23), NO-OUTDOOR
+	(5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR
 	(5490 - 5710 @ 40), (30), DFS
 
 country TH: DFS-FCC
@@ -1141,8 +1141,8 @@
 
 country TR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -1217,8 +1217,8 @@
 
 country VC: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5730 @ 160), (30), DFS
 	(5735 - 5875 @ 80), (14)
 
@@ -1253,14 +1253,14 @@
 
 country WF: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country WS: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 40), (23)
-	(5250 - 5330 @ 40), (23), DFS
+	(5170 - 5250 @ 40), (23), NO-OUTDOOR
+	(5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR
 	(5490 - 5710 @ 40), (30), DFS
 
 country XA: DFS-JP
@@ -1275,8 +1275,8 @@
 
 country YT: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
 
 country ZA: DFS-FCC
@@ -1290,6 +1290,6 @@
 
 country ZW: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (30), DFS
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0534378..409662f 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2618,7 +2618,7 @@
 			$sig_nospace =~ s/\s//g;
 			$sig_nospace = lc($sig_nospace);
 			if (defined $signatures{$sig_nospace}) {
-				WARN("BAD_SIGN_OFF",
+				WARN("DUPLICATE_SIGN_OFF",
 				     "Duplicate signature\n" . $herecurr);
 			} else {
 				$signatures{$sig_nospace} = 1;